services:
  # ==================== 基础设施 ====================
  postgres:
    image: postgres:17-bookworm
    container_name: juwan-postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${PD_USERNAME}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: ${DB_NAME}
    ports:
      - "15432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./init-db.sh:/docker-entrypoint-initdb.d/init-db.sh:ro
      - ../../desc/sql:/docker-entrypoint-initdb.d/sql:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${PD_USERNAME} -d ${DB_NAME}"]
      interval: 5s
      timeout: 3s
      start_period: 30s
      retries: 10

  redis:
    image: redis:8-alpine
    container_name: juwan-redis
    restart: unless-stopped
    ports:
      - "16379:6379"
    volumes:
      - redisdata:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 10

  rl-redis:
    image: redis:${REDIS_VERSION:-8}
    container_name: ${REDIS_CONTAINER_NAME:-rl-redis-dev-server}
    ports:
      - "6380:6379"
    restart: unless-stopped

  kafka:
    image: apache/kafka:4.0.1
    container_name: juwan-kafka
    restart: unless-stopped
    environment:
      KAFKA_NODE_ID: 1
      KAFKA_PROCESS_ROLES: broker,controller
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093
      KAFKA_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      CLUSTER_ID: juwan-dev-kafka-cluster-id
    ports:
      - "19092:9092"
    healthcheck:
      test: ["CMD-SHELL", "/opt/kafka/bin/kafka-broker-api-versions.sh --bootstrap-server localhost:9092"]
      interval: 10s
      timeout: 5s
      retries: 10

  # ==================== 共享服务 ====================
  snowflake:
    image: juwan/snowflake-rpc:dev
    container_name: juwan-snowflake
    restart: unless-stopped

  authz-adapter:
    image: juwan/authz-adapter:dev
    container_name: juwan-authz-adapter
    restart: unless-stopped
    environment:
      LISTEN_ON: 0.0.0.0:9002
      USER_RPC_TARGET: user-rpc:8080
    depends_on:
      user-rpc:
        condition: service_started

  envoy-gateway:
    image: envoyproxy/envoy:v1.31-latest
    container_name: juwan-envoy-gateway
    restart: unless-stopped
    command:
      - /usr/local/bin/envoy
      - -c
      - /etc/envoy/envoy.yaml
      - --log-level
      - info
      - --disable-hot-restart
    ports:
      - "18080:8080"
    volumes:
      - ./envoy.yaml:/etc/envoy/envoy.yaml:ro
    depends_on:
      authz-adapter:
        condition: service_started
      users-api:
        condition: service_started
      player-api:
        condition: service_started
      game-api:
        condition: service_started
      shop-api:
        condition: service_started
      order-api:
        condition: service_started
      wallet-api:
        condition: service_started
      community-api:
        condition: service_started
      objectstory-api:
        condition: service_started
      email-api:
        condition: service_started
      chat-api:
        condition: service_started

  ratelimit:
    image: envoyproxy/ratelimit:05c08d03
    container_name: rl-service
    restart: unless-stopped
    command: /bin/ratelimit
    environment:
      - REDIS_SOCKET_TYPE=tcp
      - REDIS_URL=rl-redis:6379
      - USE_STATSD=false
      - RUNTIME_ROOT=/data
      - RUNTIME_SUBDIRECTORY=ratelimit
      - RUNTIME_WATCH_ROOT=true
      - LOG_LEVEL=debug
    volumes:
      - ./rls/ratelimit.yaml:/data/ratelimit/config/ratelimit.yaml:ro
    ports:
      - "18081:8081"
      - "16070:6070"
    depends_on:
      rl-redis:
        condition: service_started

  # ==================== RPC 层 ====================
  user-rpc:
    image: juwan/users-rpc:dev
    container_name: juwan-user-rpc
    restart: unless-stopped
    env_file: .env
    environment:
      ADMIN_USERNAME: ${ADMIN_USERNAME}
      ADMIN_PASSWORD: ${ADMIN_PASSWORD}
      ADMIN_EMAIL: ${ADMIN_EMAIL}
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      snowflake:
        condition: service_started

  user-verifications-rpc:
    image: juwan/user_verifications-rpc:dev
    container_name: juwan-user-verifications-rpc
    restart: unless-stopped
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      snowflake:
        condition: service_started
      user-rpc:
        condition: service_started

  player-rpc:
    image: juwan/player-rpc:dev
    container_name: juwan-player-rpc
    restart: unless-stopped
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      snowflake:
        condition: service_started

  game-rpc:
    image: juwan/game-rpc:dev
    container_name: juwan-game-rpc
    restart: unless-stopped
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      snowflake:
        condition: service_started

  shop-rpc:
    image: juwan/shop-rpc:dev
    container_name: juwan-shop-rpc
    restart: unless-stopped
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      snowflake:
        condition: service_started
      user-rpc:
        condition: service_started

  order-rpc:
    image: juwan/order-rpc:dev
    container_name: juwan-order-rpc
    restart: unless-stopped
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      snowflake:
        condition: service_started

  wallet-rpc:
    image: juwan/wallet-rpc:dev
    container_name: juwan-wallet-rpc
    restart: unless-stopped
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      snowflake:
        condition: service_started

  community-rpc:
    image: juwan/community-rpc:dev
    container_name: juwan-community-rpc
    restart: unless-stopped
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      snowflake:
        condition: service_started

  chat-rpc:
    image: juwan/chat-rpc:dev
    container_name: juwan-chat-rpc
    restart: unless-stopped

  objectstory-rpc:
    image: juwan/objectstory-rpc:dev
    container_name: juwan-objectstory-rpc
    restart: unless-stopped
    env_file: .env

  # ==================== API 层 ====================
  users-api:
    image: juwan/users-api:dev
    container_name: juwan-users-api
    restart: unless-stopped
    env_file: .env
    ports:
      - "18801:8888"
    depends_on:
      user-rpc:
        condition: service_started
      user-verifications-rpc:
        condition: service_started

  player-api:
    image: juwan/player-api:dev
    container_name: juwan-player-api
    restart: unless-stopped
    env_file: .env
    ports:
      - "18802:8888"
    depends_on:
      player-rpc:
        condition: service_started

  game-api:
    image: juwan/game-api:dev
    container_name: juwan-game-api
    restart: unless-stopped
    env_file: .env
    ports:
      - "18803:8888"
    depends_on:
      game-rpc:
        condition: service_started

  shop-api:
    image: juwan/shop-api:dev
    container_name: juwan-shop-api
    restart: unless-stopped
    env_file: .env
    ports:
      - "18804:8888"
    depends_on:
      shop-rpc:
        condition: service_started

  order-api:
    image: juwan/order-api:dev
    container_name: juwan-order-api
    restart: unless-stopped
    env_file: .env
    ports:
      - "18805:8888"
    depends_on:
      order-rpc:
        condition: service_started
      player-rpc:
        condition: service_started
      shop-rpc:
        condition: service_started

  wallet-api:
    image: juwan/wallet-api:dev
    container_name: juwan-wallet-api
    restart: unless-stopped
    env_file: .env
    ports:
      - "18806:8888"
    depends_on:
      wallet-rpc:
        condition: service_started

  community-api:
    image: juwan/community-api:dev
    container_name: juwan-community-api
    restart: unless-stopped
    env_file: .env
    ports:
      - "18807:8888"
    depends_on:
      community-rpc:
        condition: service_started
      user-rpc:
        condition: service_started

  objectstory-api:
    image: juwan/objectstory-api:dev
    container_name: juwan-objectstory-api
    restart: unless-stopped
    env_file: .env
    ports:
      - "18808:8888"
    depends_on:
      objectstory-rpc:
        condition: service_started

  email-api:
    image: juwan/email-api:dev
    container_name: juwan-email-api
    restart: unless-stopped
    env_file: .env
    ports:
      - "18809:8888"
    depends_on:
      redis:
        condition: service_healthy
      kafka:
        condition: service_healthy

  chat-api:
    image: juwan/chat-api:dev
    container_name: juwan-chat-api
    restart: unless-stopped
    ports:
      - "18810:8888"
      - "18889:8889"
      - "18443:8443/udp"
    volumes:
      - ./certs:/etc/certs:ro
    depends_on:
      chat-rpc:
        condition: service_started

  # ==================== MQ ====================
  email-mq:
    image: juwan/email-mq:dev
    container_name: juwan-email-mq
    restart: unless-stopped
    env_file: .env
    depends_on:
      kafka:
        condition: service_healthy

volumes:
  pgdata:
    name: juwan-pgdata
  redisdata:
    name: juwan-redisdata
