# ============================================================
# INSIGHT MVP - Docker Compose (Basis-Services)
# ============================================================
# Startet alle Kerndienste der INSIGHT-Plattform.
# Observability-Stack separat: docker-compose.observability.yml
#
# Nutzung:
#   docker compose up -d
#   docker compose logs -f core
#   docker compose ps
# ============================================================

networks:
  insight-web:
    driver: bridge
    name: insight-web
  insight-db:
    driver: bridge
    name: insight-db
    internal: true
  insight-cache:
    driver: bridge
    name: insight-cache
    internal: true

volumes:
  postgres-data:
    name: insight-postgres-data
  redis-data:
    name: insight-redis-data
  step-ca-data:
    name: insight-step-ca-data
  traefik-certs:
    name: insight-traefik-certs

services:
  # --------------------------------------------------------
  # Traefik - API Gateway / Reverse Proxy
  # --------------------------------------------------------
  traefik:
    image: traefik:3
    container_name: insight-traefik
    restart: unless-stopped
    command:
      # API & Dashboard
      - "--api.dashboard=true"
      - "--api.insecure=true"
      # Entrypoints
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      # Docker Provider
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.network=insight-web"
      # File Provider (fuer dynamische Konfiguration)
      - "--providers.file.directory=/etc/traefik/dynamic"
      - "--providers.file.watch=true"
      # Logging
      - "--log.level=INFO"
      - "--accesslog=true"
      - "--accesslog.format=json"
      # Ping (fuer Healthcheck)
      - "--ping=true"
      # Metrics fuer Prometheus
      - "--metrics.prometheus=true"
      - "--metrics.prometheus.entryPoint=metrics"
      - "--entrypoints.metrics.address=:8082"
    ports:
      - "80:80"
      - "443:443"      # HTTPS (benötigt für SSO Callback)
      - "8080:8080"    # Dashboard (nur intern)
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./config/traefik/dynamic:/etc/traefik/dynamic:ro
      - traefik-certs:/certs
    networks:
      - insight-web
    labels:
      - "traefik.enable=true"
      # Dashboard Route (nur intern, via Port 8080)
      - "traefik.http.routers.dashboard.rule=Host(`172.20.10.59`) && PathPrefix(`/dashboard`)"
      - "traefik.http.routers.dashboard.service=api@internal"
      - "traefik.http.routers.dashboard.entrypoints=web"
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://localhost:8080/ping || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3

  # --------------------------------------------------------
  # PostgreSQL - Datenbank
  # --------------------------------------------------------
  postgres:
    image: postgres:16-alpine
    container_name: insight-postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${DB_USER:-insight}
      POSTGRES_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD muss gesetzt sein}
      POSTGRES_DB: ${DB_NAME:-platform_core}
      # Performance-Tuning fuer 8GB RAM VM
      POSTGRES_INITDB_ARGS: "--data-checksums"
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./config/postgres/init:/docker-entrypoint-initdb.d:ro
    networks:
      - insight-db
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-insight} -d ${DB_NAME:-platform_core}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    # Performance-Tuning via Command
    command:
      - "postgres"
      - "-c"
      - "shared_buffers=1GB"
      - "-c"
      - "effective_cache_size=4GB"
      - "-c"
      - "work_mem=16MB"
      - "-c"
      - "maintenance_work_mem=256MB"
      - "-c"
      - "max_connections=200"
      - "-c"
      - "log_min_duration_statement=500"
      - "-c"
      - "log_statement=ddl"

  # --------------------------------------------------------
  # PgBouncer - Connection Pooling
  # --------------------------------------------------------
  pgbouncer:
    image: edoburu/pgbouncer:latest
    container_name: insight-pgbouncer
    restart: unless-stopped
    environment:
      DATABASE_URL: "postgres://${DB_USER:-insight}:${DB_PASSWORD}@postgres:5432/${DB_NAME:-platform_core}"
      POOL_MODE: transaction
      MAX_CLIENT_CONN: 500
      DEFAULT_POOL_SIZE: 25
      MIN_POOL_SIZE: 5
      RESERVE_POOL_SIZE: 5
      SERVER_RESET_QUERY: "DISCARD ALL"
      SERVER_CHECK_DELAY: 30
      SERVER_CHECK_QUERY: "SELECT 1"
      AUTH_TYPE: scram-sha-256
    networks:
      - insight-db
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -h 127.0.0.1 -p 5432"]
      interval: 10s
      timeout: 5s
      retries: 3

  # --------------------------------------------------------
  # Redis - Cache, Sessions, Event Bus
  # --------------------------------------------------------
  redis:
    image: redis:7-alpine
    container_name: insight-redis
    restart: unless-stopped
    command: >
      redis-server
      --requirepass ${REDIS_PASSWORD:-}
      --maxmemory 512mb
      --maxmemory-policy allkeys-lru
      --appendonly yes
      --appendfsync everysec
      --save 60 1000
      --save 300 100
    volumes:
      - redis-data:/data
    networks:
      - insight-cache
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-}", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

  # --------------------------------------------------------
  # step-ca - Interne Certificate Authority (mTLS)
  # --------------------------------------------------------
  step-ca:
    image: smallstep/step-ca:latest
    container_name: insight-step-ca
    restart: unless-stopped
    environment:
      DOCKER_STEPCA_INIT_NAME: "INSIGHT Internal CA"
      DOCKER_STEPCA_INIT_DNS_NAMES: "step-ca,localhost"
      DOCKER_STEPCA_INIT_REMOTE_MANAGEMENT: "true"
      DOCKER_STEPCA_INIT_ACME: "true"
    volumes:
      - step-ca-data:/home/step
    networks:
      - insight-web
      - insight-db
      - insight-cache
    healthcheck:
      test: ["CMD", "step", "ca", "health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s

  # --------------------------------------------------------
  # Core-Service - NestJS Backend
  # --------------------------------------------------------
  core:
    build:
      context: ./packages/core-service
      dockerfile: Dockerfile
      target: development
    container_name: insight-core
    restart: unless-stopped
    environment:
      NODE_ENV: ${NODE_ENV:-development}
      APP_PORT: ${APP_PORT:-3000}
      APP_URL: ${APP_URL:-http://172.20.10.59}
      FRONTEND_URL: ${FRONTEND_URL:-http://172.20.10.59}
      LOG_LEVEL: ${LOG_LEVEL:-info}
      # Database (via PgBouncer)
      DATABASE_URL: "postgresql://${DB_USER:-insight}:${DB_PASSWORD}@pgbouncer:5432/${DB_NAME:-platform_core}"
      # Database (direkt fuer Migrations)
      DATABASE_URL_DIRECT: "postgresql://${DB_USER:-insight}:${DB_PASSWORD}@postgres:5432/${DB_NAME:-platform_core}"
      # Redis
      REDIS_HOST: redis
      REDIS_PORT: 6379
      REDIS_PASSWORD: ${REDIS_PASSWORD:-}
      # JWT
      JWT_PRIVATE_KEY_PATH: ${JWT_PRIVATE_KEY_PATH:-/app/keys/jwt-private.pem}
      JWT_PUBLIC_KEY_PATH: ${JWT_PUBLIC_KEY_PATH:-/app/keys/jwt-public.pem}
      JWT_ACCESS_TOKEN_EXPIRY: ${JWT_ACCESS_TOKEN_EXPIRY:-15m}
      JWT_REFRESH_TOKEN_EXPIRY: ${JWT_REFRESH_TOKEN_EXPIRY:-7d}
      JWT_ISSUER: ${JWT_ISSUER:-insight-platform}
      # Bcrypt
      BCRYPT_COST: ${BCRYPT_COST:-12}
      # CORS
      CORS_ORIGINS: ${CORS_ORIGINS:-http://172.20.10.59}
      # Microsoft Entra ID (Azure AD) SSO
      AZURE_TENANT_ID: ${AZURE_TENANT_ID:-}
      AZURE_CLIENT_ID: ${AZURE_CLIENT_ID:-}
      AZURE_CLIENT_SECRET: ${AZURE_CLIENT_SECRET:-}
      AZURE_REDIRECT_URI: ${AZURE_REDIRECT_URI:-}
      # Rate Limiting
      THROTTLE_TTL: ${THROTTLE_TTL:-60000}
      THROTTLE_LIMIT: ${THROTTLE_LIMIT:-200}
      # SSL-Admin: Pfade fuer Traefik-Zertifikate und Dynamic Config
      TRAEFIK_CERTS_PATH: /app/traefik-certs
      TRAEFIK_DYNAMIC_PATH: /app/traefik-dynamic
    volumes:
      - ./keys:/app/keys:ro
      # SSL-Admin: Core-Service schreibt Cert-Dateien und Traefik Dynamic Config
      - traefik-certs:/app/traefik-certs
      - ./config/traefik/dynamic:/app/traefik-dynamic
    networks:
      - insight-web
      - insight-db
      - insight-cache
    depends_on:
      pgbouncer:
        condition: service_healthy
      redis:
        condition: service_healthy
    labels:
      - "traefik.enable=true"
      # API Routing
      - "traefik.http.routers.core-api.rule=Host(`172.20.10.59`) && PathPrefix(`/api`)"
      - "traefik.http.routers.core-api.entrypoints=web"
      - "traefik.http.routers.core-api.service=core-api"
      # HTTPS Router fuer SSO Callback
      - "traefik.http.routers.core-api-secure.rule=Host(`172.20.10.59`) && PathPrefix(`/api`)"
      - "traefik.http.routers.core-api-secure.entrypoints=websecure"
      - "traefik.http.routers.core-api-secure.service=core-api"
      - "traefik.http.routers.core-api-secure.tls=true"
      - "traefik.http.routers.core-api-secure.middlewares=api-ratelimit"
      - "traefik.http.services.core-api.loadbalancer.server.port=3000"
      # Health-Endpunkt (ohne Auth)
      - "traefik.http.routers.core-health.rule=Host(`172.20.10.59`) && Path(`/health`)"
      - "traefik.http.routers.core-health.entrypoints=web"
      - "traefik.http.routers.core-health.service=core-api"
      # Rate Limiting Middleware
      - "traefik.http.middlewares.api-ratelimit.ratelimit.average=100"
      - "traefik.http.middlewares.api-ratelimit.ratelimit.burst=50"
      - "traefik.http.routers.core-api.middlewares=api-ratelimit"
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://localhost:3000/health || exit 1"]
      interval: 15s
      timeout: 5s
      retries: 3
      start_period: 30s

  # --------------------------------------------------------
  # Frontend - React App (via Nginx)
  # --------------------------------------------------------
  frontend:
    build:
      context: ./packages/frontend
      dockerfile: Dockerfile
      target: development
    container_name: insight-frontend
    restart: unless-stopped
    networks:
      - insight-web
    labels:
      - "traefik.enable=true"
      # Frontend Routing (Catch-All nach API)
      - "traefik.http.routers.frontend.rule=Host(`172.20.10.59`)"
      - "traefik.http.routers.frontend.entrypoints=web"
      - "traefik.http.routers.frontend.service=frontend"
      - "traefik.http.routers.frontend.priority=1"
      # HTTPS Frontend Router
      - "traefik.http.routers.frontend-secure.rule=Host(`172.20.10.59`)"
      - "traefik.http.routers.frontend-secure.entrypoints=websecure"
      - "traefik.http.routers.frontend-secure.service=frontend"
      - "traefik.http.routers.frontend-secure.tls=true"
      - "traefik.http.routers.frontend-secure.priority=1"
      - "traefik.http.services.frontend.loadbalancer.server.port=8080"
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://localhost:8080/ || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
