services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: port_nimara_crm
      POSTGRES_USER: ${DB_USER:-crm}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./docker/postgres/init.sql:/docker-entrypoint-initdb.d/01-init.sql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-crm} -d port_nimara_crm"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped
    # build-auditor HIGH: bound memory + log rotation so a stuck query or
    # noisy log doesn't fill the host disk. Postgres respects shared
    # buffers env via init.sql; the hard limit here is the container
    # ceiling.
    deploy:
      resources:
        limits:
          memory: 2g
    logging:
      driver: json-file
      options:
        max-size: "20m"
        max-file: "5"
    networks:
      - internal

  redis:
    image: redis:7-alpine
    command: redis-server --requirepass ${REDIS_PASSWORD} --maxmemory 256mb --maxmemory-policy allkeys-lru
    volumes:
      - redisdata:/data
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 512m
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
    networks:
      - internal

  crm-app:
    image: code.letsbe.solutions/letsbe/pn-new-crm/crm-app:latest
    env_file: .env
    ports:
      - "7100:3000"
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      # build-auditor H5: env.PORT is configurable (default 3000), so
      # template the port into the healthcheck URL. Otherwise overriding
      # PORT=8080 via .env makes the container healthy-check itself on
      # the wrong port and enter a restart loop.
      test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:${PORT:-3000}/api/health"]
      interval: 15s
      timeout: 5s
      retries: 3
    # Give the SIGTERM handler in src/server.ts time to drain in-flight
    # HTTP requests, close Socket.io, and disconnect Redis before Docker
    # SIGKILLs the process. The internal hard timeout is 25s.
    stop_grace_period: 30s
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 1g
    logging:
      driver: json-file
      options:
        max-size: "20m"
        max-file: "5"
    networks:
      - internal

  crm-worker:
    image: code.letsbe.solutions/letsbe/pn-new-crm/crm-worker:latest
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    # Match the app: BullMQ jobs need time to finish or be released back
    # to the queue when worker.ts handles SIGTERM.
    stop_grace_period: 30s
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 1g
    logging:
      driver: json-file
      options:
        max-size: "20m"
        max-file: "5"
    networks:
      - internal

volumes:
  pgdata:
  redisdata:

networks:
  internal:
    driver: bridge
