# syntax=docker/dockerfile:1
# Multi-stage Dockerfile for Claude Code Proxy
# Builds both Go proxy server and SvelteKit frontend in a single container
#
# Targets:
#   - (default): Production runtime image
#   - dev:       Development image with hot-reload tooling

# ============================================================================
# Stage: go-builder — compile Go proxy binary
# ============================================================================
FROM golang:1.26-alpine AS go-builder

WORKDIR /app/proxy

# Install build dependencies including gcc for CGO (sqlite)
RUN apk add --no-cache git gcc musl-dev sqlite-dev

# Copy Go modules first (cache layer)
COPY proxy/go.mod proxy/go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod \
    go mod download

# Copy Go source code and build
COPY proxy/ ./
RUN --mount=type=cache,target=/go/pkg/mod \
    --mount=type=cache,target=/root/.cache/go-build \
    CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -o /app/bin/proxy cmd/proxy/main.go

# ============================================================================
# Stage: svelte-deps — install SvelteKit dependencies (cached)
# ============================================================================
FROM node:20-alpine AS svelte-deps

WORKDIR /app/svelte
COPY svelte/package*.json ./
RUN --mount=type=cache,target=/root/.npm \
    npm ci

# ============================================================================
# Stage: svelte-builder — build SvelteKit frontend
# ============================================================================
FROM svelte-deps AS svelte-builder

COPY svelte/ ./
# shared/ is referenced by vite.config.ts (../shared/frontend/backend)
COPY shared/ /app/shared/
RUN npm run build

# ============================================================================
# Stage: svelte-prod — production SvelteKit deps only
# ============================================================================
FROM node:20-alpine AS svelte-prod

WORKDIR /app/svelte
COPY svelte/package*.json ./
RUN --mount=type=cache,target=/root/.npm \
    npm ci --omit=dev

# ============================================================================
# Stage: dev — development image with hot-reload
# ============================================================================
# CGO is required for mattn/go-sqlite3. To avoid slow first-build times
# at container start, we pre-build the binary (and warm the build cache)
# during image build. CompileDaemon then does fast incremental rebuilds.
FROM golang:1.26-alpine AS dev

# Copy Node.js 20 from official image (Alpine's repos ship Node 24 which has
# breaking module-resolution changes that break SvelteKit's virtual modules)
COPY --from=node:20-alpine /usr/local/bin/node /usr/local/bin/node
COPY --from=node:20-alpine /usr/local/lib/node_modules /usr/local/lib/node_modules
RUN ln -sf /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \
    && ln -sf /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx

# Install build deps and runtime tools
RUN apk add --no-cache \
    libstdc++ \
    git gcc musl-dev sqlite-dev \
    wget su-exec postgresql-client

# Install CompileDaemon for Go hot-reload
RUN go install github.com/githubnemo/CompileDaemon@latest

WORKDIR /app

# Pre-install Go dependencies and do initial build to warm cgo cache
COPY proxy/go.mod proxy/go.sum ./proxy/
RUN cd proxy && go mod download

COPY proxy/ ./proxy/
RUN cd proxy && CGO_ENABLED=1 go build -o /tmp/proxy-bin/proxy cmd/proxy/main.go

# Pre-install Node dependencies for svelte (layer cache)
COPY svelte/package*.json ./svelte/
RUN cd svelte && npm install

# Copy the dev entrypoint
COPY docker-entrypoint.dev.sh ./
RUN chmod +x docker-entrypoint.dev.sh

ENV PORT=3001
ENV SVELTE_PORT=5174
ENV CGO_ENABLED=1

EXPOSE 3001 5174

ENTRYPOINT ["./docker-entrypoint.dev.sh"]

# ============================================================================
# Stage: (default) — production runtime
# ============================================================================
FROM node:20-alpine

WORKDIR /app

# Install runtime dependencies (sqlite for legacy, postgresql-client for healthcheck)
RUN apk add --no-cache sqlite wget su-exec postgresql-client

# Copy built Go binary
COPY --from=go-builder /app/bin/proxy ./bin/proxy
RUN chmod +x ./bin/proxy

# Copy built SvelteKit application with production deps
COPY --from=svelte-builder /app/svelte/build ./svelte/build
COPY --from=svelte-prod /app/svelte/package*.json ./svelte/
COPY --from=svelte-prod /app/svelte/node_modules ./svelte/node_modules

# Create data directory for SQLite database
RUN mkdir -p /app/data && chown -R node:node /app

# Copy startup script
COPY docker-entrypoint.sh ./
RUN chmod +x docker-entrypoint.sh

# Environment variables with defaults
ENV PORT=3001
ENV SVELTE_PORT=5174
ENV READ_TIMEOUT=600
ENV WRITE_TIMEOUT=600
ENV IDLE_TIMEOUT=600
ENV ANTHROPIC_FORWARD_URL=https://api.anthropic.com
ENV ANTHROPIC_VERSION=2023-06-01
ENV ANTHROPIC_MAX_RETRIES=3
ENV DB_PATH=/app/data/requests.db

EXPOSE 3001 5174

HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD wget -qO- http://localhost:3001/health > /dev/null || exit 1

# Entrypoint handles privilege drop — compose overrides user to root at start
ENTRYPOINT ["./docker-entrypoint.sh"]
CMD []
