services:
  # ----------------------------------------
  # 1. Frontend (Nginx 정적 호스팅)
  # ----------------------------------------
  frontend:
    container_name: ${PROJECT_NAME}-frontend
    build:
      context: ./${FRONTEND_DIR}
      dockerfile: Dockerfile
      args:
        - BUILD_MODE=${BUILD_MODE}
        - VITE_API_BASE_URL=${BACKEND_API_URL}
        - VITE_AI_TIMEOUT_MS=${AI_TIMEOUT_MS}
        # 브라우저가 접속할 LiveKit WebSocket URL
        - VITE_LIVEKIT_URL=${LIVEKIT_WS_URL}
    expose:
      - "80"
    environment:
      - NODE_ENV=${APP_ENV}
    restart: unless-stopped
    networks:
      - app-network
      - proxy
    depends_on:
      - backend
    healthcheck:
      # localhost 는 일부 이미지에서 IPv6(::1) 로 먼저 풀려 IPv4 전용 바인딩에 연결 실패 → 127.0.0.1 고정
      test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:80/ || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 10s
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512m

  # ----------------------------------------
  # 2. Backend (HTTP API & WebSocket 통합)
  # ----------------------------------------
  backend:
    container_name: ${PROJECT_NAME}-backend
    build:
      context: ./${BACKEND_DIR}
      dockerfile: Dockerfile
    expose:
      - "${BACKEND_PORT}"
      - "${WEBSOCKET_PORT}"
    env_file:
      - ./${BACKEND_DIR}/.env.${APP_ENV}
    environment:
      - NODE_ENV=${APP_ENV}
      - PORT=${BACKEND_PORT}
      - WEBSOCKET_PORT=${WEBSOCKET_PORT}
      - CORS_ORIGIN=${CORS_ORIGIN}
      - DB_HOST=db
      - DB_PORT=5432
      - DB_USER=${DB_USER}
      - DB_PASSWORD=${DB_PASSWORD}
      - DB_NAME=${DB_NAME}
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - REDIS_PASSWORD=${REDIS_PASSWORD}
      # AI 요청 타임아웃(ms) — 프론트(VITE_AI_TIMEOUT_MS)와 동일 값을 루트 .env 에서 공급
      - AI_TIMEOUT_MS=${AI_TIMEOUT_MS}
      # 화상회의(LiveKit) — 토큰 발급에 키/시크릿, 서버 API 호출에 내부 URL 사용
      - LIVEKIT_API_KEY=${LIVEKIT_API_KEY}
      - LIVEKIT_API_SECRET=${LIVEKIT_API_SECRET}
      - LIVEKIT_URL=${LIVEKIT_URL}
      # 드라이브(NCP Object Storage) — 비시크릿만 루트에서 주입(ACCESS/SECRET 키는 backend env_file)
      - OBJECT_STORAGE_ENDPOINT=${OBJECT_STORAGE_ENDPOINT}
      - OBJECT_STORAGE_REGION=${OBJECT_STORAGE_REGION}
      - OBJECT_STORAGE_BUCKET=${OBJECT_STORAGE_BUCKET}
    restart: unless-stopped
    networks:
      - app-network
      - proxy
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      # API 는 전역 프리픽스 /api 하위에 마운트됨 — 루트(/)는 404 라 /api/health 를 프로브.
      # localhost→IPv6(::1) 회피를 위해 127.0.0.1 고정.
      test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:${BACKEND_PORT}/api/health || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 30s
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 1g

  # ----------------------------------------
  # 3. Database (PostgreSQL) — 내부 네트워크 전용
  # ----------------------------------------
  db:
    container_name: ${PROJECT_NAME}-db
    image: ${DB_IMAGE}
    expose:
      - "5432"
    environment:
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: ${DB_NAME}
    volumes:
      - ${DB_DATA_DIR}:/var/lib/postgresql/data
    restart: always
    networks:
      - app-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512m
    labels:
      - "com.centurylinklabs.watchtower.enable=true"

  # ----------------------------------------
  # 4. Redis — 내부 네트워크 전용
  # ----------------------------------------
  redis:
    container_name: ${PROJECT_NAME}-redis
    image: ${REDIS_IMAGE}
    command: redis-server --requirepass ${REDIS_PASSWORD}
    expose:
      - "6379"
    volumes:
      - ${REDIS_DATA_DIR}:/data
    restart: always
    networks:
      - app-network
    healthcheck:
      test: ["CMD-SHELL", "redis-cli -a ${REDIS_PASSWORD} ping | grep PONG"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 5s
    deploy:
      resources:
        limits:
          cpus: '0.25'
          memory: 256m
    labels:
      - "com.centurylinklabs.watchtower.enable=true"

  # ----------------------------------------
  # 5. LiveKit (화상회의 SFU) — 셀프호스팅 (운영 기본 서비스, 소스 직접 빌드)
  #    SFU 코어(pkg/sfu) 커스터마이즈를 위해 공식 이미지 대신 livekit-server/ 소스를
  #    직접 빌드한다(git subtree, v1.8.4 기준). 소스·수정은 이 레포에서 관리한다.
  #    운영(base)에서는 db·redis 처럼 항상 함께 기동된다.
  #    개발(dev)에서는 docker-compose.dev.yml 이 selfhost-livekit 프로파일로 가두어
  #    생성되지 않는다(개발은 LiveKit Cloud 사용).
  #    배포·클러스터링 가이드: livekit/DEPLOY.md
  # ----------------------------------------
  livekit:
    build:
      context: ./livekit-server
      dockerfile: Dockerfile
    container_name: ${PROJECT_NAME}-livekit
    command: --config /etc/livekit/livekit.yaml
    environment:
      # 키/시크릿은 "key: secret" 형식으로 주입(콜론+공백 때문에 전체를 따옴표로 감쌈)
      - "LIVEKIT_KEYS=${LIVEKIT_API_KEY}: ${LIVEKIT_API_SECRET}"
    expose:
      - "7880" # 시그널링/HTTP API — 리버스 프록시(TLS)에서 wss 로 라우팅
    ports:
      - "7881:7881" # ICE/TCP 폴백
      - "7882:7882/udp" # ICE/UDP (mux)
    volumes:
      # 클러스터링 시에는 redis 비밀번호가 담긴 사본을 마운트(DEPLOY.md 참고)
      - ./livekit/livekit.prod.yaml:/etc/livekit/livekit.yaml:ro
    restart: unless-stopped
    networks:
      - app-network
      - proxy
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 2g

networks:
  app-network:
    driver: bridge
  proxy:
    external: true