# EDR Freight — ephemeral Cypress e2e stack.
# Fully isolated from dev: own ports, own throwaway Postgres (tmpfs — data
# vanishes on `down`), seeded test users. Requires the same .npmrc as the main
# docker-compose.yaml (GitHub Packages auth for @tria-plc).
#
# Preferred entrypoint: the launcher (auto-up + free-port picking):
#   pnpm e2e:freight:run|open|ci|up|down   → e2e/freight/scripts/e2e.mjs
#
# Host ports are env-parameterized (E2E_*_PORT). Defaults below avoid the dev
# stacks (5273/5283/3221 are taken by the second dev checkout in
# ~/projects/nathnael/edr-platform); when a default is busy the launcher scans
# upward for a free port and remembers the choice in e2e/freight/.e2e-ports.json
# while the stack is up:
#   freight-api   3101   portal 5373   backoffice 5383
#   postgres      5533   minio  9310 (console 9311)
name: edr-freight-e2e

services:
  postgres-freight-e2e:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: edr_freight_e2e
      POSTGRES_USER: edr_e2e
      POSTGRES_PASSWORD: edr_e2e
    tmpfs:
      - /var/lib/postgresql/data
    ports:
      - "${E2E_DB_PORT:-5533}:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U edr_e2e -d edr_freight_e2e"]
      interval: 2s
      timeout: 3s
      retries: 30

  minio-e2e:
    image: minio/minio:latest
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: e2e-minio
      MINIO_ROOT_PASSWORD: e2e-minio-secret
    tmpfs:
      - /data
    ports:
      - "${E2E_MINIO_PORT:-9310}:9000"
      - "${E2E_MINIO_CONSOLE_PORT:-9311}:9001"
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 5s
      timeout: 5s
      retries: 12

  # tmpfs wipes MinIO on every restart — recreate the app bucket each boot.
  minio-init-e2e:
    image: minio/mc:latest
    depends_on:
      minio-e2e:
        condition: service_healthy
    entrypoint:
      - /bin/sh
      - -c
      - mc alias set e2e http://minio-e2e:9000 e2e-minio e2e-minio-secret && mc mb --ignore-existing e2e/fhc
    restart: "no"

  freight-api-e2e:
    build:
      context: .
      dockerfile: apps/edr-freight-api/Dockerfile
      secrets:
        - npmrc
    depends_on:
      postgres-freight-e2e:
        condition: service_healthy
      minio-e2e:
        condition: service_healthy
      minio-init-e2e:
        condition: service_completed_successfully
    environment:
      PORT: "3001"
      DB_HOST: postgres-freight-e2e
      DB_PORT: "5432"
      DB_USER: edr_e2e
      DB_PASSWORD: edr_e2e
      DB_NAME: edr_freight_e2e
      # e2e-only secrets — never reuse outside this stack
      JWT_SECRET: e2e-jwt-secret
      JWT_ACCESS_TOKEN_SECRET: e2e-access-secret
      JWT_REFRESH_TOKEN_SECRET: e2e-refresh-secret
      JWT_EXPIRES_IN: 1d
      JWT_ACCESS_TOKEN_EXPIRES: 1d
      JWT_REFRESH_TOKEN_EXPIRES: 7d
      SERVICE_AUTH_TOKEN: e2e-service-token
      # Org/unit/position boot seeders (env-gated in app code). Test USERS are
      # NOT seeded by the API — Cypress inserts them via
      # e2e/freight/cypress/fixtures/seed-users.sql before specs run.
      SEED_EDR_ORG: "true"
      SUPER_ADMIN_EMAIL: superadmin@tria.com
      SUPER_ADMIN_PHONE: "+251900000000"
      # Object storage
      MINIO_ENDPOINT: minio-e2e
      MINIO_PORT: "9000"
      MINIO_USE_SSL: "false"
      MINIO_ACCESS_KEY: e2e-minio
      MINIO_SECRET_KEY: e2e-minio-secret
      MINIO_REGION: us-east-1
      # External integrations off
      RABBITMQ_ENABLED: "false"
      FAYDA_ENABLED: "false"
      # SMS strategy has no kill switch and defaults to a real dev endpoint —
      # blackhole it so e2e never sends SMS (failures are logged, non-fatal).
      OZIKING_SMS_URL: http://127.0.0.1:9/sms
      FREIGHT_PORTAL_URL: http://localhost:${E2E_PORTAL_PORT:-5373}
    ports:
      - "${E2E_API_PORT:-3101}:3001"
    healthcheck:
      # Boot runs 240+ migrations + seeders on first start — generous start_period.
      test:
        [
          "CMD",
          "node",
          "-e",
          "fetch('http://localhost:3001/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
        ]
      interval: 5s
      timeout: 5s
      retries: 12
      start_period: 180s

  freight-portal-e2e:
    build:
      context: .
      dockerfile: infrastructure/docker/Dockerfile.web
      args:
        TURBO_FILTER: "@edr/freight-portal"
        APP_PATH: apps/edr-freight-web/portal
        # Baked at build time: browser (host or host-networked cypress
        # container) reaches the API through the published host port. A
        # non-default API port therefore forces a web image rebuild.
        VITE_API_URL: http://localhost:${E2E_API_PORT:-3101}
        VITE_BASE_API_URL: http://localhost:${E2E_API_PORT:-3101}
        VITE_USER_MANAGEMENT_BASE: /_um
        VITE_GOOGLE_MAPS_API_KEY: ""
        VITE_POSTHOG_KEY: ""
        VITE_POSTHOG_HOST: ""
      secrets:
        - npmrc
    ports:
      - "${E2E_PORTAL_PORT:-5373}:80"

  freight-backoffice-e2e:
    build:
      context: .
      dockerfile: infrastructure/docker/Dockerfile.web
      args:
        TURBO_FILTER: "@edr/freight-backoffice"
        APP_PATH: apps/edr-freight-web/backoffice
        VITE_API_URL: http://localhost:${E2E_API_PORT:-3101}
        VITE_BASE_API_URL: http://localhost:${E2E_API_PORT:-3101}
        VITE_USER_MANAGEMENT_BASE: /_um
        VITE_GOOGLE_MAPS_API_KEY: ""
        VITE_POSTHOG_KEY: ""
        VITE_POSTHOG_HOST: ""
      secrets:
        - npmrc
    ports:
      - "${E2E_BACKOFFICE_PORT:-5383}:80"

  # Headless runner — opt-in via `--profile cypress`. host network so the
  # in-container browser uses the exact same localhost URLs as `cypress open`
  # on the host (Linux only; on macOS/Windows run Cypress from the host).
  cypress:
    # Keep in sync with the cypress version in e2e/freight/package.json.
    image: cypress/included:${CYPRESS_VERSION:-15.18.1}
    profiles: ["cypress"]
    network_mode: host
    depends_on:
      freight-api-e2e:
        condition: service_healthy
    working_dir: /repo/e2e/freight
    # NOTE: host network shares the abstract X-socket namespace with the host.
    # Cypress spawns its Xvfb on :99 — run only ONE cypress container at a
    # time, and don't run it on a host whose X server occupies :99.
    entrypoint: ["cypress", "run", "--browser", "chrome"]
    environment:
      CI: "true"
      E2E_DB_URL: postgres://edr_e2e:edr_e2e@localhost:${E2E_DB_PORT:-5533}/edr_freight_e2e
      CYPRESS_BASE_URL: http://localhost:${E2E_BACKOFFICE_PORT:-5383}
      CYPRESS_API_URL: http://localhost:${E2E_API_PORT:-3101}
      CYPRESS_PORTAL_URL: http://localhost:${E2E_PORTAL_PORT:-5373}
    volumes:
      - .:/repo

secrets:
  npmrc:
    file: .npmrc
