name: capila-plus

x-app: &app
  build:
    context: .
  restart: unless-stopped

services:
  postgres:
    image: postgis/postgis:16-3.4
    environment:
      POSTGRES_DB: capila
      POSTGRES_USER: capila
      POSTGRES_PASSWORD: capila
      TZ: UTC
    ports: ["${POSTGRES_PORT:-55432}:5432"]
    volumes: ["postgres-data:/var/lib/postgresql/data"]
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U capila -d capila"]
      interval: 5s
      timeout: 3s
      retries: 20

  pgbouncer:
    image: edoburu/pgbouncer:v1.24.1-p0
    environment:
      DB_HOST: postgres
      DB_USER: capila
      DB_PASSWORD: capila
      DB_NAME: capila
      POOL_MODE: transaction
      AUTH_TYPE: scram-sha-256
      IGNORE_STARTUP_PARAMETERS: extra_float_digits,search_path
    ports: ["${PGBOUNCER_PORT:-56432}:5432"]
    depends_on:
      postgres: { condition: service_healthy }
    healthcheck:
      test: ["CMD-SHELL", "nc -z 127.0.0.1 5432"]
      interval: 5s
      timeout: 3s
      retries: 20

  redis-cache:
    image: redis:7.4-alpine
    command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
    volumes:
      - ./infrastructure/redis/cache.conf:/usr/local/etc/redis/redis.conf:ro
    ports: ["6379:6379"]
    healthcheck: &redis-health
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 20

  redis-realtime:
    image: redis:7.4-alpine
    command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
    volumes:
      - ./infrastructure/redis/realtime.conf:/usr/local/etc/redis/redis.conf:ro
      - redis-realtime-data:/data
    ports: ["6380:6379"]
    healthcheck: *redis-health

  redis-queue:
    image: redis:7.4-alpine
    command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
    volumes:
      - ./infrastructure/redis/queue.conf:/usr/local/etc/redis/redis.conf:ro
      - redis-queue-data:/data
    ports: ["6381:6379"]
    healthcheck: *redis-health

  minio:
    image: minio/minio:RELEASE.2025-07-23T15-54-02Z
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: capila
      MINIO_ROOT_PASSWORD: capila-development-only
    ports: ["9000:9000", "9001:9001"]
    volumes: ["minio-data:/data"]
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 5s
      timeout: 3s
      retries: 20

  minio-init:
    image: minio/mc:RELEASE.2025-07-21T05-28-08Z
    depends_on:
      minio: { condition: service_healthy }
    entrypoint: ["/bin/sh", "-c"]
    command:
      - "mc alias set local http://minio:9000 capila capila-development-only && mc mb --ignore-existing local/capila"

  api:
    <<: *app
    command: ["/bin/sh", "/app/infrastructure/docker/api-entrypoint.sh"]
    environment:
      NODE_ENV: development
      API_PORT: 3001
      DATABASE_URL: postgresql://capila:capila@pgbouncer:5432/capila?pgbouncer=true&schema=public
      DIRECT_DATABASE_URL: postgresql://capila:capila@postgres:5432/capila?schema=public
      REDIS_CACHE_URL: redis://redis-cache:6379
      REDIS_REALTIME_URL: redis://redis-realtime:6379
      S3_ENDPOINT: http://minio:9000
      S3_REGION: ${S3_REGION:-us-east-1}
      S3_BUCKET: ${S3_BUCKET:-capila}
      S3_ACCESS_KEY: ${S3_ACCESS_KEY:-capila}
      S3_SECRET_KEY: ${S3_SECRET_KEY:-capila-development-only}
      S3_FORCE_PATH_STYLE: "true"
      DEV_AUTH_ENABLED: "true"
      JWT_ACCESS_SECRET: development-access-secret-change-me
      JWT_REFRESH_SECRET: development-refresh-secret-change-me
      OTP_HASH_SECRET: ${OTP_HASH_SECRET:-development-otp-hash-secret-change-me}
      PASSWORD_RESET_OTP_TTL_SECONDS: ${PASSWORD_RESET_OTP_TTL_SECONDS:-300}
      PASSWORD_RESET_TOKEN_TTL_SECONDS: ${PASSWORD_RESET_TOKEN_TTL_SECONDS:-600}
      REGISTRATION_OTP_TTL_SECONDS: ${REGISTRATION_OTP_TTL_SECONDS:-300}
      REGISTRATION_TOKEN_TTL_SECONDS: ${REGISTRATION_TOKEN_TTL_SECONDS:-600}
      IDENTITY_DATA_ENCRYPTION_KEY: ${IDENTITY_DATA_ENCRYPTION_KEY:-Y2FwaWxhLWRldmVsb3BtZW50LWtleS0zMi1ieXRlcyE=}
      NATIONAL_IDENTITY_PROVIDER: ${NATIONAL_IDENTITY_PROVIDER:-mock}
      BIOMETRIC_PROVIDER: ${BIOMETRIC_PROVIDER:-mock}
      API_IR_BASE_URL: ${API_IR_BASE_URL:-https://s.api.ir}
      API_IR_TOKEN: ${API_IR_TOKEN:-}
      API_IR_TIMEOUT_MS: ${API_IR_TIMEOUT_MS:-15000}
      SHAHKAR_BASE_URL: ${SHAHKAR_BASE_URL:-https://s.api.ir}
      SHAHKAR_TOKEN: ${SHAHKAR_TOKEN:-}
      SHAHKAR_TIMEOUT_MS: ${SHAHKAR_TIMEOUT_MS:-8000}
      VIDEO_VERIFY_TOKEN: ${VIDEO_VERIFY_TOKEN:-}
      VIDEO_VERIFY_MATCHING_THRESHOLD: ${VIDEO_VERIFY_MATCHING_THRESHOLD:-80}
      VIDEO_VERIFY_LIVENESS_THRESHOLD: ${VIDEO_VERIFY_LIVENESS_THRESHOLD:-80}
      VIDEO_VERIFY_SPEECH_THRESHOLD: ${VIDEO_VERIFY_SPEECH_THRESHOLD:-50}
      BIOMETRIC_PROOF_TTL_SECONDS: ${BIOMETRIC_PROOF_TTL_SECONDS:-900}
      SMS_PROVIDER: ${SMS_PROVIDER:-mock}
      SMS_IR_BASE_URL: ${SMS_IR_BASE_URL:-https://api.sms.ir}
      SMS_IR_API_KEY: ${SMS_IR_API_KEY:-}
      SMS_IR_REGISTRATION_TEMPLATE_ID: ${SMS_IR_REGISTRATION_TEMPLATE_ID:-235824}
      SMS_IR_PASSWORD_RESET_TEMPLATE_ID: ${SMS_IR_PASSWORD_RESET_TEMPLATE_ID:-876239}
      SMS_IR_OTP_PARAMETER_NAME: ${SMS_IR_OTP_PARAMETER_NAME:-CODE}
      SMS_IR_TIMEOUT_MS: ${SMS_IR_TIMEOUT_MS:-8000}
    ports: ["3001:3001"]
    depends_on:
      pgbouncer: { condition: service_healthy }
      redis-cache: { condition: service_healthy }
      minio-init: { condition: service_completed_successfully }
      redis-realtime: { condition: service_healthy }
    healthcheck:
      test:
        [
          "CMD",
          "node",
          "-e",
          "fetch('http://localhost:3001/api/v1/health/live').then(r=>{if(!r.ok)process.exit(1)})",
        ]
      interval: 10s
      timeout: 5s
      retries: 20

  realtime:
    <<: *app
    command: ["node", "apps/realtime/dist/main.js"]
    environment:
      NODE_ENV: development
      REALTIME_PORT: 3002
      REDIS_REALTIME_URL: redis://redis-realtime:6379
      DATABASE_URL: postgresql://capila:capila@pgbouncer:5432/capila?pgbouncer=true&schema=public
      DIRECT_DATABASE_URL: postgresql://capila:capila@postgres:5432/capila?schema=public
      DEV_AUTH_ENABLED: "true"
      JWT_ACCESS_SECRET: development-access-secret-change-me
    ports: ["3002:3002"]
    depends_on:
      redis-realtime: { condition: service_healthy }
      pgbouncer: { condition: service_healthy }
    healthcheck:
      test:
        [
          "CMD",
          "node",
          "-e",
          "fetch('http://localhost:3002/health/live').then(r=>{if(!r.ok)process.exit(1)})",
        ]
      interval: 10s
      timeout: 5s
      retries: 20

  worker:
    <<: *app
    build:
      context: .
      args:
        INSTALL_FFMPEG: "true"
    command: ["node", "apps/worker/dist/main.js"]
    environment:
      NODE_ENV: development
      DATABASE_URL: postgresql://capila:capila@pgbouncer:5432/capila?pgbouncer=true&schema=public
      DIRECT_DATABASE_URL: postgresql://capila:capila@postgres:5432/capila?schema=public
      REDIS_QUEUE_URL: redis://redis-queue:6379
      REDIS_REALTIME_URL: redis://redis-realtime:6379
      S3_ENDPOINT: http://minio:9000
      S3_REGION: ${S3_REGION:-us-east-1}
      S3_BUCKET: ${S3_BUCKET:-capila}
      S3_ACCESS_KEY: ${S3_ACCESS_KEY:-capila}
      S3_SECRET_KEY: ${S3_SECRET_KEY:-capila-development-only}
      S3_FORCE_PATH_STYLE: "true"
      ENQUEUE_SAMPLE_JOB: "true"
    depends_on:
      api: { condition: service_healthy }
      redis-queue: { condition: service_healthy }
      redis-realtime: { condition: service_healthy }

  web:
    <<: *app
    command: ["pnpm", "--filter", "@capila/web", "start"]
    environment:
      NODE_ENV: production
      API_URL: http://api:3001/api/v1
      NEXT_PUBLIC_API_URL: http://localhost:3001/api/v1
      NEXT_PUBLIC_REALTIME_URL: http://localhost:3002
    ports: ["3000:3000"]
    depends_on:
      api: { condition: service_healthy }
      realtime: { condition: service_healthy }
    healthcheck:
      test:
        [
          "CMD",
          "node",
          "-e",
          "fetch('http://localhost:3000/login').then(r=>{if(!r.ok)process.exit(1)})",
        ]
      interval: 10s
      timeout: 5s
      retries: 20

volumes:
  postgres-data:
  redis-realtime-data:
  redis-queue-data:
  minio-data:
