version: "3.9"

# A single compose file that supports development and production.
# Switch modes by setting APP_ENV and COMPOSE_PROFILES to either
# "development" (default) or "production" before running docker compose up.

x-backend-common: &backend-common
  build:
    context: ./backend
    dockerfile: Dockerfile
  env_file:
    - .env
  environment:
    APP_ENV: ${APP_ENV:-development}
    DATABASE_URL: ${DATABASE_URL}
    LIVEKIT_URL: ${LIVEKIT_URL}
    LIVEKIT_API_KEY: ${LIVEKIT_API_KEY}
    LIVEKIT_API_SECRET: ${LIVEKIT_API_SECRET}
  restart: unless-stopped

x-frontend-common: &frontend-common
  build:
    context: ./frontend
    dockerfile: Dockerfile
  env_file:
    - .env
  environment:
    APP_ENV: ${APP_ENV:-development}
    # Server-side calls from Next.js hit the backend by container name
    BACKEND_URL: http://backend:8000
  restart: unless-stopped

x-postgres-common: &postgres-common
  image: pgvector/pgvector:pg16
  environment:
    POSTGRES_USER: ${POSTGRES_USER:-postgres}
    POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
    POSTGRES_DB: ${POSTGRES_DB:-app}
  volumes:
    - postgres_data:/var/lib/postgresql/data
  healthcheck:
    test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-app}"]
    interval: 10s
    timeout: 5s
    retries: 5
  restart: unless-stopped

x-livekit-common: &livekit-common
  image: livekit/livekit-server:latest
  env_file:
    - .env
  environment:
    # Keys are passed in via env; LiveKit will refuse to start without them.
    LIVEKIT_KEYS: "${LIVEKIT_API_KEY:-devkey}:${LIVEKIT_API_SECRET:-devsecret}"
    LIVEKIT_PORT: 7880
    LIVEKIT_RTC_PORT_RANGE_START: 50000
    LIVEKIT_RTC_PORT_RANGE_END: 60000
  restart: unless-stopped

services:
  backend-dev:
    <<: *backend-common
    profiles: ["development"]
    container_name: backend
    command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
    ports:
      - "8000:8000"
    volumes:
      # Mount source for hot reload; keep venv inside image
      - ./backend:/app
    depends_on:
      postgres:
        condition: service_healthy
      livekit:
        condition: service_started
    networks:
      app_internal:
        aliases: ["backend"]

  backend-prod:
    <<: *backend-common
    profiles: ["production"]
    container_name: backend
    command:
      - gunicorn
      - app.main:app
      - -k
      - uvicorn.workers.UvicornWorker
      - --bind
      - 0.0.0.0:8000
      - --workers
      - "4"
      - --timeout
      - "120"
    expose:
      - "8000"
    depends_on:
      postgres-prod:
        condition: service_healthy
      livekit-prod:
        condition: service_started
    networks:
      app_internal:
        aliases: ["backend"]
      proxy:
        aliases: ["backend"]

  frontend-dev:
    <<: *frontend-common
    build:
      context: ./frontend
      dockerfile: Dockerfile
      target: dev
    profiles: ["development"]
    container_name: frontend
    command: ["npm", "run", "dev"]
    ports:
      - "3000:3000"
    volumes:
      - ./frontend:/app
      - frontend_node_modules:/app/node_modules
    depends_on:
      backend:
        condition: service_started
    networks:
      app_internal:
        aliases: ["frontend"]

  frontend-prod:
    <<: *frontend-common
    build:
      context: ./frontend
      dockerfile: Dockerfile
      target: runner
    profiles: ["production"]
    container_name: frontend
    # Uses the standalone Next.js output from the Dockerfile
    command: ["node", "server.js"]
    expose:
      - "3000"
    depends_on:
      backend-prod:
        condition: service_started
    networks:
      app_internal:
        aliases: ["frontend"]
      proxy:
        aliases: ["frontend"]

  postgres-dev:
    <<: *postgres-common
    profiles: ["development"]
    container_name: postgres
    ports:
      - "5432:5432"
    networks:
      app_internal:
        aliases: ["postgres"]

  postgres-prod:
    <<: *postgres-common
    profiles: ["production"]
    container_name: postgres
    networks:
      app_internal:
        aliases: ["postgres"]

  livekit-dev:
    <<: *livekit-common
    profiles: ["development"]
    container_name: livekit
    ports:
      - "7880:7880"
      - "50000-60000:50000-60000/udp"
    networks:
      app_internal:
        aliases: ["livekit"]

  livekit-prod:
    <<: *livekit-common
    profiles: ["production"]
    container_name: livekit
    # UDP media must be published even in production; signaling stays internal.
    ports:
      - "50000-60000:50000-60000/udp"
    networks:
      app_internal:
        aliases: ["livekit"]
      proxy:
        aliases: ["livekit"]

volumes:
  postgres_data:
  frontend_node_modules:

networks:
  app_internal:
    # Private app network for service-to-service traffic
    driver: bridge
  proxy:
    # External network provided by the infra stack (Caddy attaches here)
    external: true
