version: '3.8'

services:
  # Apache Pulsar for Data Ingestion
  pulsar-zookeeper:
    image: apachepulsar/pulsar:latest
    container_name: pulsar-zookeeper
    restart: unless-stopped
    networks:
      - analytics-network
    ports:
      - "2181:2181"
    environment:
      - metadataStoreUrl=zk:pulsar-zookeeper:2181
    command: >
      bash -c "bin/apply-config-from-env.py conf/zookeeper.conf &&
               bin/generate-zookeeper-config.sh conf/zookeeper.conf &&
               exec bin/pulsar zookeeper"
    volumes:
      - pulsar_zookeeper_data:/pulsar/data

  pulsar-bookie:
    image: apachepulsar/pulsar:latest
    container_name: pulsar-bookie
    restart: unless-stopped
    networks:
      - analytics-network
    ports:
      - "3181:3181"
    environment:
      - clusterName=cluster-1
      - zkServers=pulsar-zookeeper:2181
      - metadataServiceUri=metadata-store:zk:pulsar-zookeeper:2181
    depends_on:
      - pulsar-zookeeper
    command: >
      bash -c "bin/apply-config-from-env.py conf/bookkeeper.conf &&
               exec bin/pulsar bookie"
    volumes:
      - pulsar_bookie_data:/pulsar/data

  pulsar-broker:
    image: apachepulsar/pulsar:latest
    container_name: pulsar-broker
    restart: unless-stopped
    networks:
      - analytics-network
    ports:
      - "6650:6650"
      - "8080:8080"
    environment:
      - metadataStoreUrl=zk:pulsar-zookeeper:2181
      - clusterName=cluster-1
      - managedLedgerDefaultEnsembleSize=1
      - managedLedgerDefaultWriteQuorum=1
      - managedLedgerDefaultAckQuorum=1
    depends_on:
      - pulsar-zookeeper
      - pulsar-bookie
    command: >
      bash -c "bin/apply-config-from-env.py conf/broker.conf &&
               exec bin/pulsar broker"

  # Apache Flink for Stream Processing
  jobmanager:
    image: flink:latest
    container_name: flink-jobmanager
    restart: unless-stopped
    networks:
      - analytics-network
    ports:
      - "8081:8081"
    command: jobmanager
    environment:
      - |
        FLINK_PROPERTIES=
        jobmanager.rpc.address: jobmanager
        parallelism.default: 2
    volumes:
      - flink_data:/opt/flink/data

  taskmanager:
    image: flink:latest
    container_name: flink-taskmanager
    restart: unless-stopped
    networks:
      - analytics-network
    depends_on:
      - jobmanager
    command: taskmanager
    scale: 2
    environment:
      - |
        FLINK_PROPERTIES=
        jobmanager.rpc.address: jobmanager
        taskmanager.numberOfTaskSlots: 2
        parallelism.default: 2
    volumes:
      - flink_data:/opt/flink/data

  # TimescaleDB for Time Series Data
  timescaledb:
    image: timescale/timescaledb:latest-pg14
    container_name: timescaledb
    restart: unless-stopped
    networks:
      - analytics-network
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_DB=analytics_timeseries
      - POSTGRES_USER=analytics_user
      - POSTGRES_PASSWORD=analytics_password
      - TIMESCALEDB_TELEMETRY=off
    volumes:
      - timescaledb_data:/var/lib/postgresql/data
      - ./scripts/timescaledb-init.sql:/docker-entrypoint-initdb.d/init.sql

  # PostgreSQL for Data Warehouse
  postgresql:
    image: postgres:14
    container_name: postgresql-warehouse
    restart: unless-stopped
    networks:
      - analytics-network
    ports:
      - "5433:5432"
    environment:
      - POSTGRES_DB=analytics_warehouse
      - POSTGRES_USER=warehouse_user
      - POSTGRES_PASSWORD=warehouse_password
    volumes:
      - postgresql_data:/var/lib/postgresql/data
      - ./scripts/postgresql-init.sql:/docker-entrypoint-initdb.d/init.sql

  # ClickHouse for OLAP Analytics
  clickhouse:
    image: clickhouse/clickhouse-server:latest
    container_name: clickhouse
    restart: unless-stopped
    networks:
      - analytics-network
    ports:
      - "8123:8123"
      - "9000:9000"
    environment:
      - CLICKHOUSE_DB=analytics_olap
      - CLICKHOUSE_USER=clickhouse_user
      - CLICKHOUSE_PASSWORD=clickhouse_password
      - CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1
    volumes:
      - clickhouse_data:/var/lib/clickhouse
      - ./scripts/clickhouse-init.sql:/docker-entrypoint-initdb.d/init.sql
    ulimits:
      nofile:
        soft: 262144
        hard: 262144

  # Redis Cluster for Caching
  redis-master:
    image: redis:alpine
    container_name: redis-master
    restart: unless-stopped
    networks:
      - analytics-network
    ports:
      - "6379:6379"
    command: redis-server --appendonly yes --replica-read-only no

  redis-replica-1:
    image: redis:alpine
    container_name: redis-replica-1
    restart: unless-stopped
    networks:
      - analytics-network
    ports:
      - "6380:6379"
    command: redis-server --appendonly yes --replicaof redis-master 6379

  redis-replica-2:
    image: redis:alpine
    container_name: redis-replica-2
    restart: unless-stopped
    networks:
      - analytics-network
    ports:
      - "6381:6379"
    command: redis-server --appendonly yes --replicaof redis-master 6379

  # Grafana for Visualization
  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    restart: unless-stopped
    networks:
      - analytics-network
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin123
      - GF_INSTALL_PLUGINS=grafana-clickhouse-datasource,redis-datasource
    volumes:
      - grafana_data:/var/lib/grafana
      - ./config/grafana/provisioning:/etc/grafana/provisioning

  # Enhanced Analytics Backend with GraphQL
  analytics-backend:
    build:
      context: .
      dockerfile: Dockerfile.enterprise
    container_name: analytics-backend
    restart: unless-stopped
    networks:
      - analytics-network
    ports:
      - "3001:3001"
      - "4000:4000"  # GraphQL endpoint
    environment:
      - NODE_ENV=production
      - TIMESCALE_URL=postgresql://analytics_user:analytics_password@timescaledb:5432/analytics_timeseries
      - WAREHOUSE_URL=postgresql://warehouse_user:warehouse_password@postgresql:5432/analytics_warehouse
      - CLICKHOUSE_URL=http://clickhouse_user:clickhouse_password@clickhouse:8123/analytics_olap
      - REDIS_MASTER_URL=redis://redis-master:6379
      - REDIS_REPLICA_URLS=redis://redis-replica-1:6379,redis://redis-replica-2:6379
      - PULSAR_SERVICE_URL=pulsar://pulsar-broker:6650
      - FLINK_JOBMANAGER_URL=http://jobmanager:8081
    depends_on:
      - timescaledb
      - postgresql
      - clickhouse
      - redis-master
      - pulsar-broker
      - jobmanager
    volumes:
      - ./logs:/app/logs

  # Data Ingestion Service
  data-ingestion:
    build:
      context: ./services/data-ingestion
      dockerfile: Dockerfile
    container_name: data-ingestion
    restart: unless-stopped
    networks:
      - analytics-network
    environment:
      - PULSAR_SERVICE_URL=pulsar://pulsar-broker:6650
      - TIMESCALE_URL=postgresql://analytics_user:analytics_password@timescaledb:5432/analytics_timeseries
    depends_on:
      - pulsar-broker
      - timescaledb

  # Stream Processing Service
  stream-processor:
    build:
      context: ./services/stream-processor
      dockerfile: Dockerfile
    container_name: stream-processor
    restart: unless-stopped
    networks:
      - analytics-network
    environment:
      - FLINK_JOBMANAGER_URL=http://jobmanager:8081
      - PULSAR_SERVICE_URL=pulsar://pulsar-broker:6650
      - CLICKHOUSE_URL=http://clickhouse_user:clickhouse_password@clickhouse:8123/analytics_olap
    depends_on:
      - jobmanager
      - pulsar-broker
      - clickhouse

networks:
  analytics-network:
    driver: bridge

volumes:
  pulsar_zookeeper_data:
  pulsar_bookie_data:
  flink_data:
  timescaledb_data:
  postgresql_data:
  clickhouse_data:
  grafana_data:
