###############################################################################
# Stalwart – Test Infrastructure
# All services are ephemeral (no volumes = fresh on every restart)
# Ports exposed on localhost; 80/443/8080 are remapped
###############################################################################

services:

  # ---------------------------------------------------------------------------
  # Init: generate shared self-signed TLS certificates
  # ---------------------------------------------------------------------------
  cert-init:
    image: alpine/openssl:latest
    volumes:
      - certs:/certs
      - ./scripts/gen-certs.sh:/gen-certs.sh:ro
    entrypoint: [ "sh", "/gen-certs.sh" ]

  # ---------------------------------------------------------------------------
  # PostgreSQL
  # ---------------------------------------------------------------------------
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: stalwart
      POSTGRES_PASSWORD: stalwart
      POSTGRES_DB: stalwart
    ports:
      - "127.0.0.1:5432:5432"
    tmpfs:
      - /var/lib/postgresql/data

  # ---------------------------------------------------------------------------
  # MySQL
  # ---------------------------------------------------------------------------
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: stalwart
      MYSQL_DATABASE: stalwart
      MYSQL_USER: stalwart
      MYSQL_PASSWORD: stalwart
    ports:
      - "127.0.0.1:3306:3306"
    tmpfs:
      - /var/lib/mysql
    command: --default-authentication-plugin=mysql_native_password

  # ---------------------------------------------------------------------------
  # FoundationDB
  # ---------------------------------------------------------------------------
  foundationdb:
    image: foundationdb/foundationdb:7.4.6
    ports:
      - "127.0.0.1:4500:4500"
    environment:
      FDB_NETWORKING_MODE: container
    volumes:
      - fdb-config:/var/fdb
    tmpfs:
      - /var/fdb/data
      - /var/fdb/logs
    healthcheck:
      test: [ "CMD-SHELL", "fdbcli --exec 'status' --timeout 3 >/dev/null 2>&1" ]
      interval: 2s
      timeout: 5s
      retries: 30
      start_period: 5s

  fdb-init:
    image: foundationdb/foundationdb:7.4.6
    depends_on:
      foundationdb:
        condition: service_healthy
    volumes:
      - fdb-config:/var/fdb
      - ./scripts/init-fdb.sh:/init-fdb.sh:ro
    entrypoint: [ "bash", "/init-fdb.sh" ]

  # ---------------------------------------------------------------------------
  # Redis
  # ---------------------------------------------------------------------------
  redis:
    image: redis:7-alpine
    ports:
      - "127.0.0.1:6379:6379"
    command: redis-server --save "" --appendonly no

  # ---------------------------------------------------------------------------
  # OpenSearch (ElasticSearch-compatible)
  # ---------------------------------------------------------------------------
  opensearch:
    image: opensearchproject/opensearch:2
    environment:
      discovery.type: single-node
      DISABLE_SECURITY_PLUGIN: "true"
      OPENSEARCH_JAVA_OPTS: "-Xms256m -Xmx256m"
      DISABLE_INSTALL_DEMO_CONFIG: "true"
    ports:
      - "127.0.0.1:9200:9200"
    tmpfs:
      - /usr/share/opensearch/data:uid=1000,gid=1000

  # ---------------------------------------------------------------------------
  # Meilisearch
  # ---------------------------------------------------------------------------
  meilisearch:
    image: getmeili/meilisearch:latest
    environment:
      MEILI_ENV: development
      MEILI_NO_ANALYTICS: "true"
      MEILI_MASTER_KEY: stalwart-master-key
    ports:
      - "127.0.0.1:7700:7700"
    tmpfs:
      - /meili_data

  # ---------------------------------------------------------------------------
  # MinIO (S3-compatible)
  # ---------------------------------------------------------------------------
  minio:
    image: minio/minio:latest
    environment:
      MINIO_ROOT_USER: minioadmin
      MINIO_ROOT_PASSWORD: minioadmin
    ports:
      - "127.0.0.1:9000:9000"
      - "127.0.0.1:9001:9001"
    command: server /data --console-address ":9001"
    tmpfs:
      - /data

  minio-init:
    image: minio/mc:latest
    depends_on:
      - minio
    volumes:
      - ./scripts/init-minio.sh:/init-minio.sh:ro
    entrypoint: [ "bash", "/init-minio.sh" ]

  # ---------------------------------------------------------------------------
  # Keycloak (OIDC Provider)  –  port 9080 (moved from 8080)
  # ---------------------------------------------------------------------------
  keycloak:
    image: quay.io/keycloak/keycloak:latest
    depends_on:
      cert-init:
        condition: service_completed_successfully
    environment:
      KC_BOOTSTRAP_ADMIN_USERNAME: admin
      KC_BOOTSTRAP_ADMIN_PASSWORD: admin
      KC_HTTP_PORT: 9080
      KC_HEALTH_ENABLED: "true"
    ports:
      - "127.0.0.1:9080:9080"
    volumes:
      - ./keycloak/stalwart-realm.json:/opt/keycloak/data/import/stalwart-realm.json:ro
      - certs:/certs:ro
    command: >
      start-dev --import-realm
    tmpfs:
      - /opt/keycloak/data:uid=1000,gid=1000

  # ---------------------------------------------------------------------------
  # OpenLDAP
  # ---------------------------------------------------------------------------
  openldap:
    image: osixia/openldap:1.5.0
    depends_on:
      cert-init:
        condition: service_completed_successfully
    environment:
      LDAP_ORGANISATION: "Stalwart Test"
      LDAP_DOMAIN: "stalwart.test"
      LDAP_BASE_DN: "dc=stalwart,dc=test"
      LDAP_ADMIN_PASSWORD: "admin"
      LDAP_READONLY_USER: "true"
      LDAP_READONLY_USER_USERNAME: "readonly"
      LDAP_READONLY_USER_PASSWORD: "readonly"
      LDAP_TLS: "true"
      LDAP_TLS_CRT_FILENAME: "cert.pem"
      LDAP_TLS_KEY_FILENAME: "key.pem"
      LDAP_TLS_CA_CRT_FILENAME: "cert.pem"
      LDAP_TLS_VERIFY_CLIENT: "never"
    ports:
      - "127.0.0.1:389:389"
      - "127.0.0.1:636:636"
    volumes:
      - ./ldap/50-users.ldif:/seed/50-users.ldif:ro
      - ./ldap/60-groups.ldif:/seed/60-groups.ldif:ro
      - certs:/certs-shared:ro
    entrypoint: [ "/bin/bash", "-c", "mkdir -p /container/service/slapd/assets/config/bootstrap/ldif/custom && cp /seed/*.ldif /container/service/slapd/assets/config/bootstrap/ldif/custom/ && cp /certs-shared/* /container/service/slapd/assets/certs/ 2>/dev/null; exec /container/tool/run" ]

  # ---------------------------------------------------------------------------
  # Pebble Challenge Test Server  –  port 8055 (management API)
  # Provides controllable DNS, HTTP, and TLS-ALPN challenge responders.
  # Use the management API to add/remove challenge responses before requesting
  # certificates from Pebble.
  # ---------------------------------------------------------------------------
  pebble-challtestsrv:
    build:
      context: ./pebble
      dockerfile: Dockerfile.challtestsrv
    image: stalwart-pebble-challtestsrv:local
    ports:
      - "127.0.0.1:8055:8055"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    restart: unless-stopped

  # ---------------------------------------------------------------------------
  # Pebble (ACME server)  –  ports 14000 (directory) + 15000 (management)
  # ---------------------------------------------------------------------------
  pebble:
    image: ghcr.io/letsencrypt/pebble:latest
    depends_on:
      - pebble-challtestsrv
    environment:
      PEBBLE_VA_NOSLEEP: "1"
      PEBBLE_WFE_NONCEREJECT: "0"
    ports:
      - "127.0.0.1:14000:14000"
      - "127.0.0.1:15000:15000"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      - ./pebble/pebble-config.json:/test/config/pebble-config.json:ro
    command: -config /test/config/pebble-config.json -dnsserver pebble-challtestsrv:8053

  # ---------------------------------------------------------------------------
  # PowerDNS (DNS with TLSA + RFC2136)  –  port 5300 (moved from 53)
  # ---------------------------------------------------------------------------
  powerdns:
    image: powerdns/pdns-auth-49:latest
    environment:
      PDNS_AUTH_API_KEY: stalwart-api-key
    ports:
      - "127.0.0.1:5300:53/tcp"
      - "127.0.0.1:5300:53/udp"
      - "127.0.0.1:8081:8081"
    volumes:
      - ./powerdns/pdns.conf:/etc/powerdns/pdns.d/stalwart.conf:ro
      - ./powerdns/init-zone.sh:/etc/powerdns/init-zone.sh:ro
      - pdns-data:/var/lib/powerdns

  powerdns-init:
    image: powerdns/pdns-auth-49:latest
    depends_on:
      - powerdns
    volumes:
      - ./powerdns/entrypoint.sh:/init.sh:ro
      - ./powerdns/init-zone.sh:/etc/powerdns/init-zone.sh:ro
      - pdns-data:/var/lib/powerdns
    entrypoint: [ "bash", "/init.sh" ]
    network_mode: "service:powerdns"

  # ---------------------------------------------------------------------------
  # NATS (message queue, core mode)
  # ---------------------------------------------------------------------------
  nats:
    image: nats:latest
    ports:
      - "127.0.0.1:4222:4222"
      - "127.0.0.1:8222:8222"
    command: "--addr 0.0.0.0 --port 4222 --http_port 8222"

# =============================================================================
# Shared volumes (ephemeral – docker compose down removes them)
# =============================================================================
volumes:
  certs:
    driver: local
  fdb-config:
    driver: local
  pdns-data:
    driver: local
