services:

  # ─────────────────────────────────────────────
  # PostgreSQL 16 — primary datastore
  # ─────────────────────────────────────────────
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: veylant
      POSTGRES_USER: veylant
      POSTGRES_PASSWORD: veylant_dev
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U veylant -d veylant"]
      interval: 5s
      timeout: 5s
      retries: 10
      start_period: 10s

  # ─────────────────────────────────────────────
  # Redis 7 — sessions, rate limiting, PII pseudonymization mappings
  # No persistence in dev (AOF/RDB disabled for fast startup)
  # ─────────────────────────────────────────────
  redis:
    image: redis:7-alpine
    command: redis-server --save "" --appendonly no
    ports:
      - "6379:6379"
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 10

  # ─────────────────────────────────────────────
  # ClickHouse 24.3 LTS — append-only audit logs and analytics
  # Pinned to LTS for stability
  # ─────────────────────────────────────────────
  clickhouse:
    image: clickhouse/clickhouse-server:24.3-alpine
    environment:
      CLICKHOUSE_DB: veylant_logs
      CLICKHOUSE_USER: veylant
      CLICKHOUSE_PASSWORD: veylant_dev
      CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1
    ports:
      - "8123:8123"   # HTTP interface (used for health check and dashboard queries)
      - "9000:9000"   # Native TCP (used by Go driver)
    volumes:
      - clickhouse_data:/var/lib/clickhouse
    healthcheck:
      test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit 1"]
      interval: 5s
      timeout: 5s
      retries: 20
      start_period: 15s
    ulimits:
      nofile:
        soft: 262144
        hard: 262144

  # ─────────────────────────────────────────────
  # Keycloak 24 — IAM, OIDC, SAML 2.0
  # start-dev: in-memory DB, no TLS — development only
  # Realm is auto-imported from deploy/keycloak/realm-export.json
  # ─────────────────────────────────────────────
  keycloak:
    image: quay.io/keycloak/keycloak:24.0
    command: ["start-dev", "--import-realm"]
    environment:
      KC_BOOTSTRAP_ADMIN_USERNAME: admin
      KC_BOOTSTRAP_ADMIN_PASSWORD: admin
      KC_DB: dev-mem
      KC_HEALTH_ENABLED: "true"
    ports:
      - "8080:8080"
    volumes:
      - ./deploy/keycloak:/opt/keycloak/data/import:ro
    healthcheck:
      test: ["CMD-SHELL", "curl -sf http://localhost:8080/health/ready || exit 1"]
      interval: 10s
      timeout: 10s
      retries: 20
      start_period: 30s   # Keycloak takes ~20s to start in dev mode

  # ─────────────────────────────────────────────
  # Veylant proxy — Go application
  # ─────────────────────────────────────────────
  proxy:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8090:8090"
    environment:
      VEYLANT_SERVER_PORT: "8090"
      VEYLANT_SERVER_ENV: "development"
      VEYLANT_DATABASE_URL: "postgres://veylant:veylant_dev@postgres:5432/veylant?sslmode=disable"
      VEYLANT_REDIS_URL: "redis://redis:6379"
      VEYLANT_KEYCLOAK_BASE_URL: "http://keycloak:8080"
      VEYLANT_KEYCLOAK_REALM: "veylant"
      VEYLANT_KEYCLOAK_CLIENT_ID: "veylant-proxy"
      VEYLANT_PII_ENABLED: "true"
      VEYLANT_PII_SERVICE_ADDR: "pii:50051"
      VEYLANT_PII_TIMEOUT_MS: "100"
      VEYLANT_PII_FAIL_OPEN: "true"
      VEYLANT_LOG_FORMAT: "console"
      VEYLANT_LOG_LEVEL: "debug"
      # Provider API keys — set via a .env file or shell environment.
      # Only providers with an API key set will be enabled at runtime.
      VEYLANT_PROVIDERS_OPENAI_API_KEY: "${OPENAI_API_KEY:-}"
      VEYLANT_PROVIDERS_ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY:-}"
      VEYLANT_PROVIDERS_MISTRAL_API_KEY: "${MISTRAL_API_KEY:-}"
      # Azure OpenAI requires resource name + deployment ID + API key.
      VEYLANT_PROVIDERS_AZURE_API_KEY: "${AZURE_OPENAI_API_KEY:-}"
      VEYLANT_PROVIDERS_AZURE_RESOURCE_NAME: "${AZURE_OPENAI_RESOURCE_NAME:-}"
      VEYLANT_PROVIDERS_AZURE_DEPLOYMENT_ID: "${AZURE_OPENAI_DEPLOYMENT_ID:-}"
      # Ollama — defaults to localhost:11434 (use host.docker.internal in Docker Desktop).
      VEYLANT_PROVIDERS_OLLAMA_BASE_URL: "${OLLAMA_BASE_URL:-http://host.docker.internal:11434/v1}"
      VEYLANT_METRICS_ENABLED: "true"
      # ClickHouse audit log (Sprint 6).
      VEYLANT_CLICKHOUSE_DSN: "clickhouse://veylant:veylant_dev@clickhouse:9000/veylant_logs"
      # AES-256-GCM key for prompt encryption — generate: openssl rand -base64 32
      # In production, inject via Vault or secret manager. Leave empty to disable.
      VEYLANT_CRYPTO_AES_KEY_BASE64: "${VEYLANT_CRYPTO_AES_KEY_BASE64:-}"
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      clickhouse:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8090/healthz || exit 1"]
      interval: 5s
      timeout: 3s
      retries: 10
      start_period: 5s

  # ─────────────────────────────────────────────
  # PII detection service — Python (Sprint 3: full pipeline)
  # Layer 1: regex (IBAN/email/phone/SSN/CB)
  # Layer 2: Presidio + spaCy NER (PERSON/LOC/ORG)
  # Pseudonymization: AES-256-GCM in Redis
  # ─────────────────────────────────────────────
  pii:
    build:
      context: ./services/pii
      dockerfile: Dockerfile
    ports:
      - "50051:50051"   # gRPC
      - "8000:8000"     # HTTP health
    environment:
      PII_GRPC_PORT: "50051"
      PII_HTTP_PORT: "8000"
      PII_REDIS_URL: "redis://redis:6379"
      # PII_ENCRYPTION_KEY must be set to a 32-byte base64-encoded key in production.
      # The default dev key is used if unset (NOT safe for production).
      PII_ENCRYPTION_KEY: "${PII_ENCRYPTION_KEY:-}"
      PII_NER_ENABLED: "true"
      PII_NER_CONFIDENCE: "0.85"
      PII_TTL_SECONDS: "3600"
    depends_on:
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8000/healthz || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 60s   # spaCy fr_core_news_lg model load takes ~30s on first start

  # ─────────────────────────────────────────────
  # Prometheus — metrics collection
  # Scrapes the proxy /metrics endpoint every 15s
  # ─────────────────────────────────────────────
  prometheus:
    image: prom/prometheus:v2.53.0
    ports:
      - "9090:9090"
    volumes:
      - ./deploy/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
      - "--storage.tsdb.path=/prometheus"
      - "--web.console.libraries=/etc/prometheus/console_libraries"
      - "--web.console.templates=/etc/prometheus/consoles"
    depends_on:
      proxy:
        condition: service_healthy

  # ─────────────────────────────────────────────
  # Grafana — metrics visualisation
  # Auto-provisioned datasource (Prometheus) + Veylant dashboard
  # Default credentials: admin / admin
  # ─────────────────────────────────────────────
  grafana:
    image: grafana/grafana:11.3.0
    ports:
      - "3001:3000"
    environment:
      GF_SECURITY_ADMIN_PASSWORD: admin
      GF_USERS_ALLOW_SIGN_UP: "false"
    volumes:
      - ./deploy/grafana/provisioning:/etc/grafana/provisioning:ro
      - ./deploy/grafana/dashboards:/var/lib/grafana/dashboards:ro
    depends_on:
      - prometheus

  # ─────────────────────────────────────────────
  # Veylant Dashboard — React SPA (Sprint 7)
  # Dev server only — production uses dist/ served by nginx
  # ─────────────────────────────────────────────
  web:
    image: node:20-alpine
    working_dir: /app
    command: sh -c "npm install && npm run dev -- --host"
    ports:
      - "3000:3000"
    volumes:
      - ./web:/app
      - /app/node_modules
    environment:
      VITE_AUTH_MODE: "dev"
      VITE_KEYCLOAK_URL: "http://localhost:8080/realms/veylant"
    depends_on:
      proxy:
        condition: service_healthy

volumes:
  postgres_data:
  clickhouse_data:
