# Docker Compose for production deployment
#
# Local testing:
#   Build images: bazel run //ci:eagle_server_load && bazel run //ci:auth_server_load
#   Run: docker compose -f docker-compose.prod.yml up
#
# Production deployment:
#   Run: docker compose -f docker-compose.prod.yml up -d
#
# Note: Shardok runs on Hetzner ARM64 server, deployed via shardok_arm64_build.yml workflow.

services:
  # Blue-green deployment: eagle-blue is the primary (production) instance
  # eagle-green is the staging instance for zero-downtime deployments
  # See scripts/deploy-blue-green.sh for deployment workflow

  eagle-blue:
    image: ${EAGLE_IMAGE:-registry.digitalocean.com/eagle0/eagle-server:latest}
    container_name: eagle-blue
    command:
      - "--shardok-interface-remote-address"
      - "${SHARDOK_ADDRESS}"
      - "--auth-service-url"
      - "auth:40033"
    ports:
      - "40032:40032"
    environment:
      OPENAI_API_KEY: "${OPENAI_API_KEY:-}"
      ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY:-}"
      GEMINI_API_KEY: "${GEMINI_API_KEY:-}"
      EAGLE_ENABLE_S3: "${EAGLE_ENABLE_S3:-false}"
      DO_SPACES_ENDPOINT: "${DO_SPACES_ENDPOINT:-https://sfo3.digitaloceanspaces.com}"
      DO_SPACES_ACCESS_KEY: "${DO_SPACES_ACCESS_KEY:-}"
      DO_SPACES_SECRET_KEY: "${DO_SPACES_SECRET_KEY:-}"
      # JWT public key for token validation (auth service handles signing)
      # Reads from /etc/eagle0/keys/public.pem via shared volume
      # Auth token for Shardok on Hetzner (required)
      SHARDOK_AUTH_TOKEN: "${SHARDOK_AUTH_TOKEN:-}"
      # Use persistent volume for save data (users, games, etc.)
      EAGLE_SAVE_DIR: "/app/saves"
      EAGLE_ARCHIVE_DIR: "/app/archived"
      SENTRY_DSN: "${SENTRY_DSN:-}"
      SENTRY_ENVIRONMENT: "production"
    volumes:
      - ./saves:/app/saves           # Game saves and user database
      - ./archived:/app/archived     # Archived completed games
      - ./jfr:/app/jfr  # JFR recordings - dump with: docker exec eagle-blue jcmd 1 JFR.dump filename=/app/jfr/profile.jfr
      - jvm-tmp:/tmp  # Shared with jfr-sidecar for JVM attach socket files
      - jwt-keys:/etc/eagle0/keys:ro  # JWT public key from auth service (read-only)
    depends_on:
      - auth
    restart: unless-stopped
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "5"
    healthcheck:
      test: ["CMD-SHELL", "nc -z localhost 40032 || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s

  eagle-green:
    image: ${EAGLE_IMAGE_NEW:-registry.digitalocean.com/eagle0/eagle-server:latest}
    container_name: eagle-green
    profiles: ["blue-green"]  # Only started during blue-green deployment
    command:
      - "--shardok-interface-remote-address"
      - "${SHARDOK_ADDRESS}"
      - "--auth-service-url"
      - "auth:40033"
    ports:
      - "40034:40032"  # Different host port for staging
    environment:
      OPENAI_API_KEY: "${OPENAI_API_KEY:-}"
      ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY:-}"
      GEMINI_API_KEY: "${GEMINI_API_KEY:-}"
      EAGLE_ENABLE_S3: "${EAGLE_ENABLE_S3:-false}"
      DO_SPACES_ENDPOINT: "${DO_SPACES_ENDPOINT:-https://sfo3.digitaloceanspaces.com}"
      DO_SPACES_ACCESS_KEY: "${DO_SPACES_ACCESS_KEY:-}"
      DO_SPACES_SECRET_KEY: "${DO_SPACES_SECRET_KEY:-}"
      # JWT public key for token validation (auth service handles signing)
      # Reads from /etc/eagle0/keys/public.pem via shared volume
      SHARDOK_AUTH_TOKEN: "${SHARDOK_AUTH_TOKEN:-}"
      EAGLE_SAVE_DIR: "/app/saves"
      EAGLE_ARCHIVE_DIR: "/app/archived"
      SENTRY_DSN: "${SENTRY_DSN:-}"
      SENTRY_ENVIRONMENT: "production"
    volumes:
      - ./saves:/app/saves           # Same save directory as blue
      - ./archived:/app/archived     # Same archive directory as blue
      - ./jfr:/app/jfr               # JFR recordings (same as blue)
      - jvm-tmp:/tmp                 # Shared with jfr-sidecar-green for JVM attach socket files
      - jwt-keys:/etc/eagle0/keys:ro # JWT public key from auth service (read-only)
    depends_on:
      - auth
    restart: "no"  # Don't auto-restart during deployment
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "5"
    healthcheck:
      test: ["CMD-SHELL", "nc -z localhost 40032 || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 6
      start_period: 60s

  # Backward compatibility alias - for scripts that reference 'eagle' service
  eagle:
    extends:
      service: eagle-blue

  auth:
    image: ${AUTH_IMAGE:-registry.digitalocean.com/eagle0/auth-server:latest}
    container_name: auth-server
    environment:
      # gRPC port for Auth service
      AUTH_GRPC_PORT: "40033"
      # HTTP port for OAuth callbacks
      AUTH_HTTP_PORT: "8080"
      # User data persistence directory
      AUTH_DATA_DIR: "/app/data"
      # Legacy path for migrating users from Eagle (Phase 1 migration)
      AUTH_LEGACY_DATA_DIR: "/app/saves/auth"
      # OAuth provider credentials
      DISCORD_CLIENT_ID: "${DISCORD_CLIENT_ID:-}"
      DISCORD_CLIENT_SECRET: "${DISCORD_CLIENT_SECRET:-}"
      GOOGLE_CLIENT_ID: "${GOOGLE_CLIENT_ID:-}"
      GOOGLE_CLIENT_SECRET: "${GOOGLE_CLIENT_SECRET:-}"
      GH_OAUTH_CLIENT_ID: "${GH_OAUTH_CLIENT_ID:-}"
      GH_OAUTH_CLIENT_SECRET: "${GH_OAUTH_CLIENT_SECRET:-}"
      # Apple Sign-In credentials
      APPLE_SIGNIN_CLIENT_ID: "${APPLE_SIGNIN_CLIENT_ID:-}"
      APPLE_TEAM_ID: "${APPLE_TEAM_ID:-}"
      APPLE_SIGNIN_KEY_ID: "${APPLE_SIGNIN_KEY_ID:-}"
      APPLE_SIGNIN_PRIVATE_KEY: "${APPLE_SIGNIN_PRIVATE_KEY:-}"
      # Twitch OAuth credentials
      TWITCH_CLIENT_ID: "${TWITCH_CLIENT_ID:-}"
      TWITCH_CLIENT_SECRET: "${TWITCH_CLIENT_SECRET:-}"
      # Server base URL for OAuth callbacks
      SERVER_BASE_URL: "${SERVER_BASE_URL:-https://prod.eagle0.net}"
      # JWT keys - PEM files in volume, bootstrapped from JWK on first run
      JWT_KEYS_PATH: "/etc/eagle0/keys"
      JWT_PRIVATE_KEY: "${JWT_PRIVATE_KEY:-}"
      # Fastmail JMAP API for sending invitation emails
      FASTMAIL_API_TOKEN: "${FASTMAIL_API_TOKEN:-}"
      FASTMAIL_FROM_EMAIL: "${FASTMAIL_FROM_EMAIL:-}"
      FASTMAIL_FROM_NAME: "${FASTMAIL_FROM_NAME:-}"
      # Require invitation codes for new user registration
      REQUIRE_INVITATION_CODE: "true"
    # Note: port 40033 is exposed via nginx, not directly
    volumes:
      - jwt-keys:/etc/eagle0/keys  # Shared JWT keys with Eagle
      - ./auth-data:/app/data      # User database persistence
      - ./saves:/app/saves:ro      # Read-only access to Eagle's saves for migration
    restart: unless-stopped
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"
    healthcheck:
      test: ["CMD-SHELL", "nc -z localhost 40033 || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

  # Note: Shardok runs on Hetzner ARM64 server, not in this docker-compose.
  # Configure SHARDOK_ADDRESS to point to the Hetzner instance.

  nginx:
    image: nginx:alpine
    container_name: nginx
    ports:
      - "443:443"
      - "80:80"
      - "40033:40033"  # Go Auth service gRPC (Phase 2 direct client connections)
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certbot/conf:/etc/letsencrypt:ro
      - ./certbot/www:/var/www/certbot:ro
      - ./auth:/etc/nginx/auth:ro
    depends_on:
      - admin
    # Note: nginx connects to eagle via EAGLE_ADDR (default: eagle-blue:40032)
    # For blue-green deployments, update EAGLE_ADDR in .env before switching
    restart: unless-stopped
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"

  admin:
    image: ${ADMIN_IMAGE:-registry.digitalocean.com/eagle0/admin-server:latest}
    container_name: admin-server
    command:
      - "--eagle-addr"
      - "${EAGLE_ADDR:-eagle-blue:40032}"  # Can be switched for blue-green
      - "--auth-addr"
      - "auth:40033"
      - "--jfr-sidecar-addr"
      - "${JFR_SIDECAR_ADDR:-jfr-sidecar:8081}"  # Can be switched for blue-green
      - "--http-port"
      - "8080"
      - "--maps-dir"
      - "/app/maps"
    environment:
      # Secret for CI to authenticate client update notifications
      NOTIFY_SECRET: "${NOTIFY_SECRET:-}"
      # S3/Spaces credentials for What's New storage (uses eagle0-assets bucket)
      DO_SPACES_ENDPOINT: "${DO_SPACES_ENDPOINT:-https://sfo3.digitaloceanspaces.com}"
      DO_SPACES_ACCESS_KEY: "${ADMIN_S3_ACCESS_KEY:-}"
      DO_SPACES_SECRET_KEY: "${ADMIN_S3_SECRET_KEY:-}"
      # GitHub PAT for map editor PR creation (scoped to contents:write + pull_requests:write)
      GITHUB_TOKEN: "${GITHUB_TOKEN:-}"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    # No external port - accessed via nginx at admin.eagle0.net
    depends_on:
      - auth
    # Note: admin connects to eagle via EAGLE_ADDR and jfr-sidecar via JFR_SIDECAR_ADDR
    # For blue-green deployments, set both in .env before switching
    restart: unless-stopped
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"
    healthcheck:
      test: ["CMD-SHELL", "wget -q --spider http://localhost:8080/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

  jfr-sidecar:
    image: ${JFR_SIDECAR_IMAGE:-registry.digitalocean.com/eagle0/jfr-sidecar:latest}
    container_name: jfr-sidecar
    # Share PID namespace with Eagle to access its JVM via jcmd
    # For blue-green: use JFR_SIDECAR_ADDR=jfr-sidecar-green:8081 when green is active
    pid: "service:eagle-blue"
    volumes:
      - jvm-tmp:/tmp  # Shared with Eagle for JVM attach socket files
    depends_on:
      - eagle-blue
    restart: unless-stopped
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "2"
    healthcheck:
      test: ["CMD-SHELL", "wget -q --spider http://localhost:8081/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

  jfr-sidecar-green:
    image: ${JFR_SIDECAR_IMAGE:-registry.digitalocean.com/eagle0/jfr-sidecar:latest}
    container_name: jfr-sidecar-green
    profiles: ["blue-green"]  # Only started during blue-green deployment
    # Share PID namespace with Eagle green instance
    pid: "service:eagle-green"
    volumes:
      - jvm-tmp:/tmp  # Shared with Eagle for JVM attach socket files
    depends_on:
      - eagle-green
    restart: "no"  # Don't auto-restart during deployment
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "2"
    healthcheck:
      test: ["CMD-SHELL", "wget -q --spider http://localhost:8081/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

  certbot:
    image: certbot/certbot
    container_name: certbot
    volumes:
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

volumes:
  jvm-tmp:
    # Shared /tmp for JVM attach socket files between Eagle and jfr-sidecar
  jwt-keys:
    # Shared JWT RSA keys between Eagle and auth service

networks:
  default:
    driver: bridge
    enable_ipv6: true
    ipam:
      config:
        - subnet: 172.28.0.0/16
        - subnet: fd00:dead:beef::/48
