# Production stack: load-balanced web replicas + workers + PgBouncer + Redis
# Usage:
#   cp .env.example .env.production   # fill secrets
#   docker compose -f docker-compose.prod.yml up --build --scale web=3 --scale worker=2

name: cuppa-prod

x-app-env: &app-env
  NODE_ENV: production
  AUTH_SECRET: ${AUTH_SECRET}
  NEXTAUTH_URL: ${NEXTAUTH_URL:-http://localhost}
  NEXT_PUBLIC_ENABLE_DEMO_LOGIN: "false"
  # App → PgBouncer (transaction pool, low connections per replica)
  DATABASE_URL: postgresql://postgres:postgres@pgbouncer:6432/cuppa?schema=public&pgbouncer=true&connection_limit=5
  REDIS_URL: redis://redis:6379
  SMTP_HOST: ${SMTP_HOST}
  SMTP_PORT: ${SMTP_PORT}
  SMTP_USER: ${SMTP_USER}
  SMTP_PASS: ${SMTP_PASS}
  SMTP_FROM: ${SMTP_FROM}
  PG_BOSS_MAX_CONNECTIONS: "10"

x-worker-env: &worker-env
  NODE_ENV: production
  WORKER_DATABASE_URL: postgresql://postgres:postgres@postgres:5432/cuppa?schema=public
  SMTP_HOST: ${SMTP_HOST}
  SMTP_PORT: ${SMTP_PORT}
  SMTP_USER: ${SMTP_USER}
  SMTP_PASS: ${SMTP_PASS}
  SMTP_FROM: ${SMTP_FROM}
  EMAIL_WORKER_PROCESSES: ${EMAIL_WORKER_PROCESSES:-2}
  EMAIL_WORKER_CONCURRENCY: ${EMAIL_WORKER_CONCURRENCY:-25}
  EMAIL_WORKER_BATCH_SIZE: ${EMAIL_WORKER_BATCH_SIZE:-50}
  SMTP_POOL_SIZE: ${SMTP_POOL_SIZE:-10}
  PG_BOSS_MAX_CONNECTIONS: ${PG_BOSS_MAX_CONNECTIONS:-30}
  WORKER_HEALTH_PORT: "8081"

services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: cuppa
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -d cuppa"]
      interval: 10s
      timeout: 5s
      retries: 5

  pgbouncer:
    image: edoburu/pgbouncer:1.22.1-p0
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    volumes:
      - ./deploy/pgbouncer/pgbouncer.ini:/etc/pgbouncer/pgbouncer.ini:ro
      - ./deploy/pgbouncer/userlist.txt:/etc/pgbouncer/userlist.txt:ro
    ports:
      - "6432:6432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -h localhost -p 6432 -U postgres || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    restart: unless-stopped
    command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5

  migrate:
    build:
      context: .
      dockerfile: Dockerfile
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      DIRECT_DATABASE_URL: postgresql://postgres:postgres@postgres:5432/cuppa?schema=public
    entrypoint: ["sh", "-c", "npx prisma db push && npx prisma db seed"]
    restart: "no"

  web:
    build:
      context: .
      dockerfile: Dockerfile
    restart: unless-stopped
    environment:
      <<: *app-env
    depends_on:
      migrate:
        condition: service_completed_successfully
      pgbouncer:
        condition: service_started
      redis:
        condition: service_healthy
    expose:
      - "3000"
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/api/ready"]
      interval: 15s
      timeout: 5s
      retries: 3
      start_period: 40s
    deploy:
      resources:
        limits:
          cpus: "1"
          memory: 1G

  worker:
    build:
      context: .
      dockerfile: Dockerfile.worker
    restart: unless-stopped
    environment:
      <<: *worker-env
    depends_on:
      migrate:
        condition: service_completed_successfully
      postgres:
        condition: service_healthy
    expose:
      - "8081"
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8081/live"]
      interval: 15s
      timeout: 5s
      retries: 3
      start_period: 20s
    deploy:
      resources:
        limits:
          cpus: "1"
          memory: 512M

  nginx:
    image: nginx:1.27-alpine
    restart: unless-stopped
    depends_on:
      web:
        condition: service_healthy
    ports:
      - "80:80"
    volumes:
      - ./deploy/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./deploy/nginx/proxy_params.conf:/etc/nginx/proxy_params.conf:ro

volumes:
  postgres_data:
  redis_data:
