version: '3.8'

# Xpeditis - Stack STAGING/PREPROD
# Portainer Stack avec Traefik reverse proxy
# Domaines: staging.xpeditis.com (frontend) | api-staging.xpeditis.com (backend)

services:
  # PostgreSQL Database
  postgres-staging:
    image: postgres:15-alpine
    container_name: xpeditis-postgres-staging
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${POSTGRES_DB:-xpeditis_staging}
      POSTGRES_USER: ${POSTGRES_USER:-xpeditis}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?error}
      PGDATA: /var/lib/postgresql/data/pgdata
    volumes:
      - postgres_data_staging:/var/lib/postgresql/data
    networks:
      - xpeditis_internal_staging
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-xpeditis}"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Redis Cache
  redis-staging:
    image: redis:7-alpine
    container_name: xpeditis-redis-staging
    restart: unless-stopped
    command: redis-server --requirepass ${REDIS_PASSWORD:?error} --maxmemory 512mb --maxmemory-policy allkeys-lru
    volumes:
      - redis_data_staging:/data
    networks:
      - xpeditis_internal_staging
    healthcheck:
      test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5

  # Backend API (NestJS)
  backend-staging:
    image: ${DOCKER_REGISTRY:-docker.io}/${BACKEND_IMAGE:-xpeditis/backend}:${BACKEND_TAG:-staging-latest}
    container_name: xpeditis-backend-staging
    restart: unless-stopped
    depends_on:
      postgres-staging:
        condition: service_healthy
      redis-staging:
        condition: service_healthy
    environment:
      # Application
      NODE_ENV: staging
      PORT: 4000

      # Database
      DATABASE_HOST: postgres-staging
      DATABASE_PORT: 5432
      DATABASE_NAME: ${POSTGRES_DB:-xpeditis_staging}
      DATABASE_USER: ${POSTGRES_USER:-xpeditis}
      DATABASE_PASSWORD: ${POSTGRES_PASSWORD:?error}
      DATABASE_SYNC: "false"
      DATABASE_LOGGING: "true"

      # Redis
      REDIS_HOST: redis-staging
      REDIS_PORT: 6379
      REDIS_PASSWORD: ${REDIS_PASSWORD:?error}

      # JWT
      JWT_SECRET: ${JWT_SECRET:?error}
      JWT_ACCESS_EXPIRATION: 15m
      JWT_REFRESH_EXPIRATION: 7d

      # CORS
      CORS_ORIGIN: https://staging.xpeditis.com,http://localhost:3000

      # Sentry (Monitoring)
      SENTRY_DSN: ${SENTRY_DSN:-}
      SENTRY_ENVIRONMENT: staging
      SENTRY_TRACES_SAMPLE_RATE: 0.1
      SENTRY_PROFILES_SAMPLE_RATE: 0.05

      # AWS S3 (or MinIO)
      AWS_REGION: ${AWS_REGION:-eu-west-3}
      AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:?error}
      AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:?error}
      S3_BUCKET_DOCUMENTS: ${S3_BUCKET_DOCUMENTS:-xpeditis-staging-documents}
      S3_BUCKET_UPLOADS: ${S3_BUCKET_UPLOADS:-xpeditis-staging-uploads}

      # Email (AWS SES or SMTP)
      EMAIL_SERVICE: ${EMAIL_SERVICE:-ses}
      EMAIL_FROM: ${EMAIL_FROM:-noreply@staging.xpeditis.com}
      EMAIL_FROM_NAME: Xpeditis Staging
      AWS_SES_REGION: ${AWS_SES_REGION:-eu-west-1}

      # Carrier APIs (Sandbox)
      MAERSK_API_URL: ${MAERSK_API_URL_SANDBOX:-https://sandbox.api.maersk.com}
      MAERSK_API_KEY: ${MAERSK_API_KEY_SANDBOX:-}
      MSC_API_URL: ${MSC_API_URL_SANDBOX:-}
      MSC_API_KEY: ${MSC_API_KEY_SANDBOX:-}

      # Security
      RATE_LIMIT_GLOBAL: 200
      RATE_LIMIT_AUTH: 10
      RATE_LIMIT_SEARCH: 50
      RATE_LIMIT_BOOKING: 30

    volumes:
      - backend_logs_staging:/app/logs
    networks:
      - xpeditis_internal_staging
      - traefik_network
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_network"

      # HTTPS Route
      - "traefik.http.routers.xpeditis-backend-staging.rule=Host(`api-staging.xpeditis.com`)"
      - "traefik.http.routers.xpeditis-backend-staging.entrypoints=websecure"
      - "traefik.http.routers.xpeditis-backend-staging.tls=true"
      - "traefik.http.routers.xpeditis-backend-staging.tls.certresolver=letsencrypt"
      - "traefik.http.routers.xpeditis-backend-staging.priority=100"
      - "traefik.http.services.xpeditis-backend-staging.loadbalancer.server.port=4000"
      - "traefik.http.routers.xpeditis-backend-staging.middlewares=xpeditis-backend-staging-headers,xpeditis-backend-staging-security"

      # HTTP → HTTPS Redirect
      - "traefik.http.routers.xpeditis-backend-staging-http.rule=Host(`api-staging.xpeditis.com`)"
      - "traefik.http.routers.xpeditis-backend-staging-http.entrypoints=web"
      - "traefik.http.routers.xpeditis-backend-staging-http.priority=100"
      - "traefik.http.routers.xpeditis-backend-staging-http.middlewares=xpeditis-backend-staging-redirect"
      - "traefik.http.routers.xpeditis-backend-staging-http.service=xpeditis-backend-staging"
      - "traefik.http.middlewares.xpeditis-backend-staging-redirect.redirectscheme.scheme=https"
      - "traefik.http.middlewares.xpeditis-backend-staging-redirect.redirectscheme.permanent=true"

      # Middleware Headers
      - "traefik.http.middlewares.xpeditis-backend-staging-headers.headers.customRequestHeaders.X-Forwarded-Proto=https"
      - "traefik.http.middlewares.xpeditis-backend-staging-headers.headers.customRequestHeaders.X-Forwarded-For="
      - "traefik.http.middlewares.xpeditis-backend-staging-headers.headers.customRequestHeaders.X-Real-IP="

      # Security Headers
      - "traefik.http.middlewares.xpeditis-backend-staging-security.headers.frameDeny=true"
      - "traefik.http.middlewares.xpeditis-backend-staging-security.headers.contentTypeNosniff=true"
      - "traefik.http.middlewares.xpeditis-backend-staging-security.headers.browserXssFilter=true"
      - "traefik.http.middlewares.xpeditis-backend-staging-security.headers.stsSeconds=31536000"
      - "traefik.http.middlewares.xpeditis-backend-staging-security.headers.stsIncludeSubdomains=true"
      - "traefik.http.middlewares.xpeditis-backend-staging-security.headers.stsPreload=true"

      # Rate Limiting
      - "traefik.http.middlewares.xpeditis-backend-staging-ratelimit.ratelimit.average=100"
      - "traefik.http.middlewares.xpeditis-backend-staging-ratelimit.ratelimit.burst=200"

      # Health Check
      - "traefik.http.services.xpeditis-backend-staging.loadbalancer.healthcheck.path=/health"
      - "traefik.http.services.xpeditis-backend-staging.loadbalancer.healthcheck.interval=30s"
      - "traefik.http.services.xpeditis-backend-staging.loadbalancer.healthcheck.timeout=5s"

    healthcheck:
      test: ["CMD", "node", "-e", "require('http').get('http://localhost:4000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  # Frontend (Next.js)
  frontend-staging:
    image: ${DOCKER_REGISTRY:-docker.io}/${FRONTEND_IMAGE:-xpeditis/frontend}:${FRONTEND_TAG:-staging-latest}
    container_name: xpeditis-frontend-staging
    restart: unless-stopped
    depends_on:
      - backend-staging
    environment:
      NODE_ENV: staging
      NEXT_PUBLIC_API_URL: https://api-staging.xpeditis.com
      NEXT_PUBLIC_APP_URL: https://staging.xpeditis.com
      NEXT_PUBLIC_SENTRY_DSN: ${NEXT_PUBLIC_SENTRY_DSN:-}
      NEXT_PUBLIC_SENTRY_ENVIRONMENT: staging
      NEXT_PUBLIC_GA_MEASUREMENT_ID: ${NEXT_PUBLIC_GA_MEASUREMENT_ID:-}

      # Backend API for SSR (internal)
      API_URL: http://backend-staging:4000

    networks:
      - xpeditis_internal_staging
      - traefik_network
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_network"

      # HTTPS Route
      - "traefik.http.routers.xpeditis-frontend-staging.rule=Host(`staging.xpeditis.com`)"
      - "traefik.http.routers.xpeditis-frontend-staging.entrypoints=websecure"
      - "traefik.http.routers.xpeditis-frontend-staging.tls=true"
      - "traefik.http.routers.xpeditis-frontend-staging.tls.certresolver=letsencrypt"
      - "traefik.http.routers.xpeditis-frontend-staging.priority=100"
      - "traefik.http.services.xpeditis-frontend-staging.loadbalancer.server.port=3000"
      - "traefik.http.routers.xpeditis-frontend-staging.middlewares=xpeditis-frontend-staging-headers,xpeditis-frontend-staging-security,xpeditis-frontend-staging-compress"

      # HTTP → HTTPS Redirect
      - "traefik.http.routers.xpeditis-frontend-staging-http.rule=Host(`staging.xpeditis.com`)"
      - "traefik.http.routers.xpeditis-frontend-staging-http.entrypoints=web"
      - "traefik.http.routers.xpeditis-frontend-staging-http.priority=100"
      - "traefik.http.routers.xpeditis-frontend-staging-http.middlewares=xpeditis-frontend-staging-redirect"
      - "traefik.http.routers.xpeditis-frontend-staging-http.service=xpeditis-frontend-staging"
      - "traefik.http.middlewares.xpeditis-frontend-staging-redirect.redirectscheme.scheme=https"
      - "traefik.http.middlewares.xpeditis-frontend-staging-redirect.redirectscheme.permanent=true"

      # Middleware Headers
      - "traefik.http.middlewares.xpeditis-frontend-staging-headers.headers.customRequestHeaders.X-Forwarded-Proto=https"
      - "traefik.http.middlewares.xpeditis-frontend-staging-headers.headers.customRequestHeaders.X-Forwarded-For="
      - "traefik.http.middlewares.xpeditis-frontend-staging-headers.headers.customRequestHeaders.X-Real-IP="

      # Security Headers
      - "traefik.http.middlewares.xpeditis-frontend-staging-security.headers.frameDeny=true"
      - "traefik.http.middlewares.xpeditis-frontend-staging-security.headers.contentTypeNosniff=true"
      - "traefik.http.middlewares.xpeditis-frontend-staging-security.headers.browserXssFilter=true"
      - "traefik.http.middlewares.xpeditis-frontend-staging-security.headers.stsSeconds=31536000"
      - "traefik.http.middlewares.xpeditis-frontend-staging-security.headers.stsIncludeSubdomains=true"
      - "traefik.http.middlewares.xpeditis-frontend-staging-security.headers.stsPreload=true"
      - "traefik.http.middlewares.xpeditis-frontend-staging-security.headers.customResponseHeaders.X-Robots-Tag=noindex,nofollow"

      # Compression
      - "traefik.http.middlewares.xpeditis-frontend-staging-compress.compress=true"

      # Health Check
      - "traefik.http.services.xpeditis-frontend-staging.loadbalancer.healthcheck.path=/api/health"
      - "traefik.http.services.xpeditis-frontend-staging.loadbalancer.healthcheck.interval=30s"
      - "traefik.http.services.xpeditis-frontend-staging.loadbalancer.healthcheck.timeout=5s"

    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:3000/api/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

networks:
  xpeditis_internal_staging:
    driver: bridge
    name: xpeditis_internal_staging
  traefik_network:
    external: true

volumes:
  postgres_data_staging:
    name: xpeditis_postgres_data_staging
  redis_data_staging:
    name: xpeditis_redis_data_staging
  backend_logs_staging:
    name: xpeditis_backend_logs_staging
